From 9f2fc81df2ad6731b521bd7dfd523ee10f63be90 Mon Sep 17 00:00:00 2001 From: Joshua Reisenauer Date: Mon, 30 May 2016 15:34:29 -0700 Subject: update to openal --- src/raylib.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/raylib.h') diff --git a/src/raylib.h b/src/raylib.h index d0231be2..a0cfc7a0 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -926,7 +926,7 @@ void SetMusicPitch(int index, float pitch); RawAudioContext InitRawAudioContext(int sampleRate, int channels, bool floatingPoint); void CloseRawAudioContext(RawAudioContext ctx); -int BufferRawAudioContext(RawAudioContext ctx, void *data, int numberElements); // returns number of elements buffered +int BufferRawAudioContext(RawAudioContext ctx, void *data, unsigned short numberElements); // returns number of elements buffered #ifdef __cplusplus } -- cgit v1.2.3 From caa7bc366b949310fbb9c7eafbb9fa7050e1514a Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 31 May 2016 00:51:55 +0200 Subject: Reviewed DrawLight() function and some tweaks --- examples/shaders_standard_lighting.c | 12 ++++++------ src/models.c | 29 +++++++++++++++++++++++++++ src/raylib.h | 18 ++++++++--------- src/rlgl.c | 38 +++++++----------------------------- 4 files changed, 51 insertions(+), 46 deletions(-) (limited to 'src/raylib.h') diff --git a/examples/shaders_standard_lighting.c b/examples/shaders_standard_lighting.c index 6b5cd9f5..10416f7f 100644 --- a/examples/shaders_standard_lighting.c +++ b/examples/shaders_standard_lighting.c @@ -33,12 +33,12 @@ int main() Camera camera = {{ 4.0f, 4.0f, 4.0f }, { 0.0f, 1.5f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f }; Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position - Model dwarf = LoadModel("resources/model/dwarf.obj"); // Load OBJ model + Model dwarf = LoadModel("resources/model/dwarf.obj"); // Load OBJ model Material material = LoadStandardMaterial(); - material.texDiffuse = LoadTexture("resources/model/dwarf_diffuse.png"); // Load model diffuse texture - material.texNormal = LoadTexture("resources/model/dwarf_normal.png"); // Load model normal texture + material.texDiffuse = LoadTexture("resources/model/dwarf_diffuse.png"); // Load model diffuse texture + material.texNormal = LoadTexture("resources/model/dwarf_normal.png"); // Load model normal texture material.texSpecular = LoadTexture("resources/model/dwarf_specular.png"); // Load model specular texture material.colDiffuse = (Color){255, 255, 255, 255}; material.colAmbient = (Color){0, 0, 10, 255}; @@ -46,8 +46,6 @@ int main() material.glossiness = 50.0f; dwarf.material = material; // Apply material to model - - Model dwarf2 = LoadModel("resources/model/dwarf.obj"); // Load OBJ model Light spotLight = CreateLight(LIGHT_SPOT, (Vector3){3.0f, 5.0f, 2.0f}, (Color){255, 255, 255, 255}); spotLight->target = (Vector3){0.0f, 0.0f, 0.0f}; @@ -91,7 +89,9 @@ int main() DrawModel(dwarf, position, 2.0f, WHITE); // Draw 3d model with texture - DrawLights(); // Draw all created lights in 3D world + DrawLight(spotLight); // Draw spot light + DrawLight(dirLight); // Draw directional light + DrawLight(pointLight); // Draw point light DrawGrid(10, 1.0f); // Draw a grid diff --git a/src/models.c b/src/models.c index 092a43fc..8c5ed914 100644 --- a/src/models.c +++ b/src/models.c @@ -569,6 +569,35 @@ void DrawGizmo(Vector3 position) rlPopMatrix(); } + +// Draw light in 3D world +void DrawLight(Light light) +{ + switch (light->type) + { + case LIGHT_POINT: + { + DrawSphereWires(light->position, 0.3f*light->intensity, 4, 8, (light->enabled ? light->diffuse : BLACK)); + Draw3DCircle(light->position, light->radius, 0.0f, (Vector3){ 0, 0, 0 }, (light->enabled ? light->diffuse : BLACK)); + Draw3DCircle(light->position, light->radius, 90.0f, (Vector3){ 1, 0, 0 }, (light->enabled ? light->diffuse : BLACK)); + Draw3DCircle(light->position, light->radius, 90.0f, (Vector3){ 0, 1, 0 }, (light->enabled ? light->diffuse : BLACK)); + } break; + case LIGHT_DIRECTIONAL: + { + Draw3DLine(light->position, light->target, (light->enabled ? light->diffuse : BLACK)); + DrawSphereWires(light->position, 0.3f*light->intensity, 4, 8, (light->enabled ? light->diffuse : BLACK)); + DrawCubeWires(light->target, 0.3f, 0.3f, 0.3f, (light->enabled ? light->diffuse : BLACK)); + } break; + case LIGHT_SPOT: + { + Draw3DLine(light->position, light->target, (light->enabled ? light->diffuse : BLACK)); + DrawCylinderWires(light->position, 0.0f, 0.3f*light->coneAngle/50, 0.6f, 5, (light->enabled ? light->diffuse : BLACK)); + DrawCubeWires(light->target, 0.3f, 0.3f, 0.3f, (light->enabled ? light->diffuse : BLACK)); + } break; + default: break; + } +} + // Load a 3d model (from file) Model LoadModel(const char *fileName) { diff --git a/src/raylib.h b/src/raylib.h index dfec956d..cba73e52 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -431,18 +431,18 @@ typedef struct Model { // Light type typedef struct LightData { - int id; - int type; // LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT - bool enabled; + unsigned int id; // Light id + int type; // Light type: LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT + bool enabled; // Light enabled - Vector3 position; - Vector3 target; // Used on LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target) - float radius; // Lost of light intensity with distance (world distance) + Vector3 position; // Light position + Vector3 target; // Light target: LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target) + float radius; // Light attenuation radius light intensity reduced with distance (world distance) - Color diffuse; // Light color + Color diffuse; // Light diffuse color float intensity; // Light intensity level - float coneAngle; // Spot light max angle + float coneAngle; // Light cone max angle: LIGHT_SPOT } LightData, *Light; // Light types @@ -817,6 +817,7 @@ void DrawPlane(Vector3 centerPos, Vector2 size, Color color); void DrawRay(Ray ray, Color color); // Draw a ray line void DrawGrid(int slices, float spacing); // Draw a grid (centered at (0, 0, 0)) void DrawGizmo(Vector3 position); // Draw simple gizmo +void DrawLight(Light light); // Draw light in 3D world //DrawTorus(), DrawTeapot() are useless... //------------------------------------------------------------------------------------ @@ -873,7 +874,6 @@ void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat); // S void SetBlendMode(int mode); // Set blending mode (alpha, additive, multiplied) Light CreateLight(int type, Vector3 position, Color diffuse); // Create a new light, initialize it and add to pool -void DrawLights(void); // Draw all created lights in 3D world void DestroyLight(Light light); // Destroy a light and take it out of the list //---------------------------------------------------------------------------------- diff --git a/src/rlgl.c b/src/rlgl.c index 0f68953e..97a92a4d 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -1069,6 +1069,13 @@ void rlglClose(void) // Delete default white texture glDeleteTextures(1, &whiteTexture); TraceLog(INFO, "[TEX ID %i] Unloaded texture data (base white texture) from VRAM", whiteTexture); + + // Unload lights + if (lightsCount > 0) + { + for (int i = 0; i < lightsCount; i++) free(lights[i]); + lightsCount = 0; + } free(draws); #endif @@ -2292,37 +2299,6 @@ Light CreateLight(int type, Vector3 position, Color diffuse) return light; } -// Draw all created lights in 3D world -void DrawLights(void) -{ - for (int i = 0; i < lightsCount; i++) - { - switch (lights[i]->type) - { - case LIGHT_POINT: - { - DrawSphereWires(lights[i]->position, 0.3f*lights[i]->intensity, 4, 8, (lights[i]->enabled ? lights[i]->diffuse : BLACK)); - Draw3DCircle(lights[i]->position, lights[i]->radius, 0.0f, (Vector3){ 0, 0, 0 }, (lights[i]->enabled ? lights[i]->diffuse : BLACK)); - Draw3DCircle(lights[i]->position, lights[i]->radius, 90.0f, (Vector3){ 1, 0, 0 }, (lights[i]->enabled ? lights[i]->diffuse : BLACK)); - Draw3DCircle(lights[i]->position, lights[i]->radius, 90.0f, (Vector3){ 0, 1, 0 }, (lights[i]->enabled ? lights[i]->diffuse : BLACK)); - } break; - case LIGHT_DIRECTIONAL: - { - Draw3DLine(lights[i]->position, lights[i]->target, (lights[i]->enabled ? lights[i]->diffuse : BLACK)); - DrawSphereWires(lights[i]->position, 0.3f*lights[i]->intensity, 4, 8, (lights[i]->enabled ? lights[i]->diffuse : BLACK)); - DrawCubeWires(lights[i]->target, 0.3f, 0.3f, 0.3f, (lights[i]->enabled ? lights[i]->diffuse : BLACK)); - } break; - case LIGHT_SPOT: - { - Draw3DLine(lights[i]->position, lights[i]->target, (lights[i]->enabled ? lights[i]->diffuse : BLACK)); - DrawCylinderWires(lights[i]->position, 0.0f, 0.3f*lights[i]->coneAngle/50, 0.6f, 5, (lights[i]->enabled ? lights[i]->diffuse : BLACK)); - DrawCubeWires(lights[i]->target, 0.3f, 0.3f, 0.3f, (lights[i]->enabled ? lights[i]->diffuse : BLACK)); - } break; - default: break; - } - } -} - // Destroy a light and take it out of the list void DestroyLight(Light light) { -- cgit v1.2.3 From cac2a66debd0f2d3ef8195940f8e2744d539d19a Mon Sep 17 00:00:00 2001 From: raysan5 Date: Tue, 31 May 2016 17:11:02 +0200 Subject: Improved library consistency Functions renamed to improve library consistency --- examples/shaders_custom_uniform.c | 12 +++++++----- examples/shaders_postprocessing.c | 12 +++++++----- examples/shaders_shapes_textures.c | 18 +++++++++--------- examples/textures_particles_trail_blending.c | 24 +++++++++++++----------- src/raylib.h | 8 +++++--- src/rlgl.c | 18 ++++++++++++------ src/rlgl.h | 9 ++++++--- 7 files changed, 59 insertions(+), 42 deletions(-) (limited to 'src/raylib.h') diff --git a/examples/shaders_custom_uniform.c b/examples/shaders_custom_uniform.c index 74077143..516d5087 100644 --- a/examples/shaders_custom_uniform.c +++ b/examples/shaders_custom_uniform.c @@ -33,7 +33,7 @@ int main() Camera camera = {{ 3.0f, 3.0f, 3.0f }, { 0.0f, 1.5f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f }; Model dwarf = LoadModel("resources/model/dwarf.obj"); // Load OBJ model - Texture2D texture = LoadTexture("resources/model/dwarf_diffuse.png"); // Load model texture + Texture2D texture = LoadTexture("resources/model/dwarf_diffuse.png"); // Load model texture (diffuse map) SetModelTexture(&dwarf, texture); // Bind texture to model Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position @@ -94,10 +94,12 @@ int main() EndTextureMode(); // End drawing to texture (now we have a texture available for next passes) - SetCustomShader(shader); - // NOTE: Render texture must be y-flipped due to default OpenGL coordinates (left-bottom) - DrawTextureRec(target.texture, (Rectangle){ 0, 0, target.texture.width, -target.texture.height }, (Vector2){ 0, 0 }, WHITE); - SetDefaultShader(); + BeginShaderMode(shader); + + // NOTE: Render texture must be y-flipped due to default OpenGL coordinates (left-bottom) + DrawTextureRec(target.texture, (Rectangle){ 0, 0, target.texture.width, -target.texture.height }, (Vector2){ 0, 0 }, WHITE); + + EndShaderMode(); DrawText("(c) Dwarf 3D model by David Moreno", screenWidth - 200, screenHeight - 20, 10, GRAY); diff --git a/examples/shaders_postprocessing.c b/examples/shaders_postprocessing.c index e9fafe15..5e8b5a80 100644 --- a/examples/shaders_postprocessing.c +++ b/examples/shaders_postprocessing.c @@ -33,7 +33,7 @@ int main() Camera camera = {{ 3.0f, 3.0f, 3.0f }, { 0.0f, 1.5f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f }; Model dwarf = LoadModel("resources/model/dwarf.obj"); // Load OBJ model - Texture2D texture = LoadTexture("resources/model/dwarf_diffuse.png"); // Load model texture + Texture2D texture = LoadTexture("resources/model/dwarf_diffuse.png"); // Load model texture (diffuse map) SetModelTexture(&dwarf, texture); // Bind texture to model Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position @@ -80,10 +80,12 @@ int main() EndTextureMode(); // End drawing to texture (now we have a texture available for next passes) - SetCustomShader(shader); - // NOTE: Render texture must be y-flipped due to default OpenGL coordinates (left-bottom) - DrawTextureRec(target.texture, (Rectangle){ 0, 0, target.texture.width, -target.texture.height }, (Vector2){ 0, 0 }, WHITE); - SetDefaultShader(); + BeginShaderMode(shader); + + // NOTE: Render texture must be y-flipped due to default OpenGL coordinates (left-bottom) + DrawTextureRec(target.texture, (Rectangle){ 0, 0, target.texture.width, -target.texture.height }, (Vector2){ 0, 0 }, WHITE); + + EndShaderMode(); DrawText("(c) Dwarf 3D model by David Moreno", screenWidth - 200, screenHeight - 20, 10, DARKGRAY); diff --git a/examples/shaders_shapes_textures.c b/examples/shaders_shapes_textures.c index 1b1142fa..0a14469f 100644 --- a/examples/shaders_shapes_textures.c +++ b/examples/shaders_shapes_textures.c @@ -65,16 +65,16 @@ int main() // Activate our custom shader to be applied on next shapes/textures drawings - SetCustomShader(shader); + BeginShaderMode(shader); - DrawText("USING CUSTOM SHADER", 190, 40, 10, RED); + DrawText("USING CUSTOM SHADER", 190, 40, 10, RED); - DrawRectangle(250 - 60, 90, 120, 60, RED); - DrawRectangleGradient(250 - 90, 170, 180, 130, MAROON, GOLD); - DrawRectangleLines(250 - 40, 320, 80, 60, ORANGE); + DrawRectangle(250 - 60, 90, 120, 60, RED); + DrawRectangleGradient(250 - 90, 170, 180, 130, MAROON, GOLD); + DrawRectangleLines(250 - 40, 320, 80, 60, ORANGE); // Activate our default shader for next drawings - SetDefaultShader(); + EndShaderMode(); DrawText("USING DEFAULT SHADER", 370, 40, 10, RED); @@ -89,12 +89,12 @@ int main() DrawPoly((Vector2){430, 320}, 6, 80, 0, BROWN); // Activate our custom shader to be applied on next shapes/textures drawings - SetCustomShader(shader); + BeginShaderMode(shader); - DrawTexture(sonic, 380, -10, WHITE); // Using custom shader + DrawTexture(sonic, 380, -10, WHITE); // Using custom shader // Activate our default shader for next drawings - SetDefaultShader(); + EndShaderMode(); EndDrawing(); //---------------------------------------------------------------------------------- diff --git a/examples/textures_particles_trail_blending.c b/examples/textures_particles_trail_blending.c index 76cd0423..0b47c790 100644 --- a/examples/textures_particles_trail_blending.c +++ b/examples/textures_particles_trail_blending.c @@ -102,20 +102,22 @@ int main() ClearBackground(DARKGRAY); - SetBlendMode(blending); + BeginBlendMode(blending); - // Draw active particles - for (int i = 0; i < MAX_PARTICLES; i++) - { - if (mouseTail[i].active) DrawTexturePro(smoke, (Rectangle){ 0, 0, smoke.width, smoke.height }, - (Rectangle){ mouseTail[i].position.x, mouseTail[i].position.y, smoke.width*mouseTail[i].size, smoke.height*mouseTail[i].size }, - (Vector2){ smoke.width*mouseTail[i].size/2, smoke.height*mouseTail[i].size/2 }, mouseTail[i].rotation, - Fade(mouseTail[i].color, mouseTail[i].alpha)); - } + // Draw active particles + for (int i = 0; i < MAX_PARTICLES; i++) + { + if (mouseTail[i].active) DrawTexturePro(smoke, (Rectangle){ 0, 0, smoke.width, smoke.height }, + (Rectangle){ mouseTail[i].position.x, mouseTail[i].position.y, smoke.width*mouseTail[i].size, smoke.height*mouseTail[i].size }, + (Vector2){ smoke.width*mouseTail[i].size/2, smoke.height*mouseTail[i].size/2 }, mouseTail[i].rotation, + Fade(mouseTail[i].color, mouseTail[i].alpha)); + } + + EndBlendMode(); - DrawText("PRESS SPACE to CHANGE BLENDING MODE", 180, 20, 20, RAYWHITE); + DrawText("PRESS SPACE to CHANGE BLENDING MODE", 180, 20, 20, BLACK); - if (blending == BLEND_ALPHA) DrawText("ALPHA BLENDING", 290, screenHeight - 40, 20, RAYWHITE); + if (blending == BLEND_ALPHA) DrawText("ALPHA BLENDING", 290, screenHeight - 40, 20, BLACK); else DrawText("ADDITIVE BLENDING", 280, screenHeight - 40, 20, RAYWHITE); EndDrawing(); diff --git a/src/raylib.h b/src/raylib.h index cba73e52..5bef3698 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -860,8 +860,7 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p //------------------------------------------------------------------------------------ Shader LoadShader(char *vsFileName, char *fsFileName); // Load a custom shader and bind default locations void UnloadShader(Shader shader); // Unload a custom shader from memory -void SetDefaultShader(void); // Set default shader to be used in batch draw -void SetCustomShader(Shader shader); // Set custom shader to be used in batch draw + Shader GetDefaultShader(void); // Get default shader Shader GetStandardShader(void); // Get default shader Texture2D GetDefaultTexture(void); // Get default texture @@ -871,7 +870,10 @@ void SetShaderValue(Shader shader, int uniformLoc, float *value, int size); // S void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size); // Set shader uniform value (int) void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat); // Set shader uniform value (matrix 4x4) -void SetBlendMode(int mode); // Set blending mode (alpha, additive, multiplied) +void BeginShaderMode(Shader shader); // Begin custom shader drawing +void EndShaderMode(void); // End custom shader drawing (use default shader) +void BeginBlendMode(int mode); // Begin blending mode (alpha, additive, multiplied) +void EndBlendMode(void); // End blending mode (reset to default: alpha blending) Light CreateLight(int type, Vector3 position, Color diffuse); // Create a new light, initialize it and add to pool void DestroyLight(Light light); // Destroy a light and take it out of the list diff --git a/src/rlgl.c b/src/rlgl.c index 97a92a4d..5c4c9c01 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -2157,7 +2157,7 @@ void UnloadShader(Shader shader) } // Set custom shader to be used on batch draw -void SetCustomShader(Shader shader) +void BeginShaderMode(Shader shader) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) if (currentShader.id != shader.id) @@ -2169,10 +2169,10 @@ void SetCustomShader(Shader shader) } // Set default shader to be used in batch draw -void SetDefaultShader(void) +void EndShaderMode(void) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - SetCustomShader(defaultShader); + BeginShaderMode(defaultShader); #endif } @@ -2254,9 +2254,9 @@ void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat) #endif } -// Set blending mode (alpha, additive, multiplied) -// NOTE: Only 3 blending modes predefined -void SetBlendMode(int mode) +// Begin blending mode (alpha, additive, multiplied) +// NOTE: Only 3 blending modes supported, default blend mode is alpha +void BeginBlendMode(int mode) { if ((blendMode != mode) && (mode < 3)) { @@ -2274,6 +2274,12 @@ void SetBlendMode(int mode) } } +// End blending mode (reset to default: alpha blending) +void EndBlendMode(void) +{ + BeginBlendMode(BLEND_ALPHA); +} + // Create a new light, initialize it and add to pool Light CreateLight(int type, Vector3 position, Color diffuse) { diff --git a/src/rlgl.h b/src/rlgl.h index 23ad29fb..ccf2b36a 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -317,9 +317,9 @@ void *rlglReadTexturePixels(Texture2D texture); // Read text //------------------------------------------------------------------------------------ Shader LoadShader(char *vsFileName, char *fsFileName); // Load a custom shader and bind default locations void UnloadShader(Shader shader); // Unload a custom shader from memory -void SetCustomShader(Shader shader); // Set custom shader to be used in batch draw -void SetDefaultShader(void); // Set default shader to be used in batch draw + Shader GetDefaultShader(void); // Get default shader +Shader GetStandardShader(void); // Get default shader Texture2D GetDefaultTexture(void); // Get default texture int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location @@ -327,7 +327,10 @@ void SetShaderValue(Shader shader, int uniformLoc, float *value, int size); // S void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size); // Set shader uniform value (int) void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat); // Set shader uniform value (matrix 4x4) -void SetBlendMode(int mode); // Set blending mode (alpha, additive, multiplied) +void BeginShaderMode(Shader shader); // Begin custom shader drawing +void EndShaderMode(void); // End custom shader drawing (use default shader) +void BeginBlendMode(int mode); // Begin blending mode (alpha, additive, multiplied) +void EndBlendMode(void); // End blending mode (reset to default: alpha blending) Light CreateLight(int type, Vector3 position, Color diffuse); // Create a new light, initialize it and add to pool void DestroyLight(Light light); // Destroy a light and take it out of the list -- cgit v1.2.3 From 302ec438dd8a5483e4fcf81d4bd80ac7d09e6a61 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Tue, 31 May 2016 18:15:53 +0200 Subject: Removed colTint, tint color is colDiffuse Tint color could be applied to colDiffuse... but what's the best way? Replace it? Multiply by? A point to think about... --- examples/resources/shaders/glsl330/grayscale.fs | 4 ++-- examples/resources/shaders/standard.fs | 7 +++---- examples/shaders_standard_lighting.c | 4 ++-- src/models.c | 5 ++--- src/raylib.h | 1 - src/rlgl.c | 3 --- src/rlgl.h | 21 ++++++++++----------- 7 files changed, 19 insertions(+), 26 deletions(-) (limited to 'src/raylib.h') diff --git a/examples/resources/shaders/glsl330/grayscale.fs b/examples/resources/shaders/glsl330/grayscale.fs index d4a8824f..5b3e11be 100644 --- a/examples/resources/shaders/glsl330/grayscale.fs +++ b/examples/resources/shaders/glsl330/grayscale.fs @@ -6,7 +6,7 @@ in vec4 fragColor; // Input uniform values uniform sampler2D texture0; -uniform vec4 fragTintColor; +uniform vec4 colDiffuse; // Output fragment color out vec4 finalColor; @@ -16,7 +16,7 @@ out vec4 finalColor; void main() { // Texel color fetching from texture sampler - vec4 texelColor = texture(texture0, fragTexCoord)*fragTintColor*fragColor; + vec4 texelColor = texture(texture0, fragTexCoord)*colDiffuse*fragColor; // Convert texel color to grayscale using NTSC conversion weights float gray = dot(texelColor.rgb, vec3(0.299, 0.587, 0.114)); diff --git a/examples/resources/shaders/standard.fs b/examples/resources/shaders/standard.fs index bb9e6865..e5916031 100644 --- a/examples/resources/shaders/standard.fs +++ b/examples/resources/shaders/standard.fs @@ -11,7 +11,6 @@ uniform sampler2D texture0; uniform sampler2D texture1; uniform sampler2D texture2; -uniform vec4 colTint; uniform vec4 colAmbient; uniform vec4 colDiffuse; uniform vec4 colSpecular; @@ -55,7 +54,7 @@ vec3 CalcPointLight(Light l, vec3 n, vec3 v, float s) spec = pow(dot(n, h), 3 + glossiness)*s; } - return (diff*l.diffuse.rgb*colDiffuse.rgb + spec*colSpecular.rgb); + return (diff*l.diffuse.rgb + spec*colSpecular.rgb); } vec3 CalcDirectionalLight(Light l, vec3 n, vec3 v, float s) @@ -74,7 +73,7 @@ vec3 CalcDirectionalLight(Light l, vec3 n, vec3 v, float s) } // Combine results - return (diff*l.intensity*l.diffuse.rgb*colDiffuse.rgb + spec*colSpecular.rgb); + return (diff*l.intensity*l.diffuse.rgb + spec*colSpecular.rgb); } vec3 CalcSpotLight(Light l, vec3 n, vec3 v, float s) @@ -150,5 +149,5 @@ void main() } // Calculate final fragment color - finalColor = vec4(texelColor.rgb*lighting*colTint.rgb, texelColor.a*colTint.a); + finalColor = vec4(texelColor.rgb*lighting*colDiffuse.rgb, texelColor.a*colDiffuse.a); } diff --git a/examples/shaders_standard_lighting.c b/examples/shaders_standard_lighting.c index 10416f7f..ccbe74ca 100644 --- a/examples/shaders_standard_lighting.c +++ b/examples/shaders_standard_lighting.c @@ -40,9 +40,9 @@ int main() material.texDiffuse = LoadTexture("resources/model/dwarf_diffuse.png"); // Load model diffuse texture material.texNormal = LoadTexture("resources/model/dwarf_normal.png"); // Load model normal texture material.texSpecular = LoadTexture("resources/model/dwarf_specular.png"); // Load model specular texture - material.colDiffuse = (Color){255, 255, 255, 255}; + material.colDiffuse = WHITE; material.colAmbient = (Color){0, 0, 10, 255}; - material.colSpecular = (Color){255, 255, 255, 255}; + material.colSpecular = WHITE; material.glossiness = 50.0f; dwarf.material = material; // Apply material to model diff --git a/src/models.c b/src/models.c index 8c5ed914..962a6470 100644 --- a/src/models.c +++ b/src/models.c @@ -779,8 +779,7 @@ Material LoadDefaultMaterial(void) material.texDiffuse = GetDefaultTexture(); // White texture (1x1 pixel) //material.texNormal; // NOTE: By default, not set //material.texSpecular; // NOTE: By default, not set - - material.colTint = WHITE; // Tint color + material.colDiffuse = WHITE; // Diffuse color material.colAmbient = WHITE; // Ambient color material.colSpecular = WHITE; // Specular color @@ -1298,7 +1297,7 @@ void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rota //Matrix matModel = MatrixMultiply(model.transform, matTransform); // Transform to world-space coordinates model.transform = MatrixMultiply(MatrixMultiply(matScale, matRotation), matTranslation); - model.material.colTint = tint; + model.material.colDiffuse = tint; // TODO: Multiply tint color by diffuse color? rlglDrawMesh(model.mesh, model.material, model.transform); } diff --git a/src/raylib.h b/src/raylib.h index 5bef3698..271c0e42 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -414,7 +414,6 @@ typedef struct Material { Texture2D texNormal; // Normal texture (binded to shader mapTexture1Loc) Texture2D texSpecular; // Specular texture (binded to shader mapTexture2Loc) - Color colTint; // Tint color Color colDiffuse; // Diffuse color Color colAmbient; // Ambient color Color colSpecular; // Specular color diff --git a/src/rlgl.c b/src/rlgl.c index 5c4c9c01..6a2adeb2 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -1800,9 +1800,6 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) // Setup shader uniforms for lights SetShaderLights(material.shader); - // Upload to shader material.colSpecular - glUniform4f(glGetUniformLocation(material.shader.id, "colTint"), (float)material.colTint.r/255, (float)material.colTint.g/255, (float)material.colTint.b/255, (float)material.colTint.a/255); - // Upload to shader material.colAmbient glUniform4f(glGetUniformLocation(material.shader.id, "colAmbient"), (float)material.colAmbient.r/255, (float)material.colAmbient.g/255, (float)material.colAmbient.b/255, (float)material.colAmbient.a/255); diff --git a/src/rlgl.h b/src/rlgl.h index ccf2b36a..336f6019 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -201,8 +201,7 @@ typedef enum { OPENGL_11 = 1, OPENGL_33, OPENGL_ES_20 } GlVersion; Texture2D texDiffuse; // Diffuse texture Texture2D texNormal; // Normal texture Texture2D texSpecular; // Specular texture - - Color colTint; // Tint color + Color colDiffuse; // Diffuse color Color colAmbient; // Ambient color Color colSpecular; // Specular color @@ -212,18 +211,18 @@ typedef enum { OPENGL_11 = 1, OPENGL_33, OPENGL_ES_20 } GlVersion; // Light type typedef struct LightData { - int id; - int type; // LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT - bool enabled; + unsigned int id; // Light id + int type; // Light type: LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT + bool enabled; // Light enabled - Vector3 position; - Vector3 target; // Used on LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target) - float radius; // Lost of light intensity with distance (world distance) + Vector3 position; // Light position + Vector3 target; // Light target: LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target) + float radius; // Light attenuation radius light intensity reduced with distance (world distance) - Color diffuse; // Use Vector3 diffuse - float intensity; + Color diffuse; // Light diffuse color + float intensity; // Light intensity level - float coneAngle; // Spot light max angle + float coneAngle; // Light cone max angle: LIGHT_SPOT } LightData, *Light; // Color blending modes (pre-defined) -- cgit v1.2.3 From d17a0cee1aa53978387e68be58d901bffd1ac0a9 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Tue, 31 May 2016 19:12:37 +0200 Subject: Review text formatting (spacing, tabs...) --- examples/resources/shaders/standard.fs | 8 ++- src/core.c | 18 +++--- src/raylib.h | 96 +++++++++++++++--------------- src/raymath.h | 2 +- src/rlgl.c | 2 +- src/rlgl.h | 103 +++++++++++++++++---------------- src/shapes.c | 2 +- 7 files changed, 117 insertions(+), 114 deletions(-) (limited to 'src/raylib.h') diff --git a/examples/resources/shaders/standard.fs b/examples/resources/shaders/standard.fs index e5916031..e5a6d1bc 100644 --- a/examples/resources/shaders/standard.fs +++ b/examples/resources/shaders/standard.fs @@ -88,8 +88,10 @@ vec3 CalcSpotLight(Light l, vec3 n, vec3 v, float s) // Spot attenuation float attenuation = clamp(dot(n, lightToSurface), 0.0, 1.0); attenuation = dot(lightToSurface, -lightDir); + float lightToSurfaceAngle = degrees(acos(attenuation)); if (lightToSurfaceAngle > l.coneAngle) attenuation = 0.0; + float falloff = (l.coneAngle - lightToSurfaceAngle)/l.coneAngle; // Combine diffuse and attenuation @@ -103,7 +105,7 @@ vec3 CalcSpotLight(Light l, vec3 n, vec3 v, float s) spec = pow(dot(n, h), 3 + glossiness)*s; } - return falloff*(diffAttenuation*l.diffuse.rgb + spec*colSpecular.rgb); + return (falloff*(diffAttenuation*l.diffuse.rgb + spec*colSpecular.rgb)); } void main() @@ -122,7 +124,7 @@ void main() vec3 lighting = colAmbient.rgb; // Calculate normal texture color fetching or set to maximum normal value by default - if(useNormal == 1) + if (useNormal == 1) { n *= texture(texture1, fragTexCoord).rgb; n = normalize(n); @@ -130,7 +132,7 @@ void main() // Calculate specular texture color fetching or set to maximum specular value by default float spec = 1.0; - if(useSpecular == 1) spec *= normalize(texture(texture2, fragTexCoord).r); + if (useSpecular == 1) spec *= normalize(texture(texture2, fragTexCoord).r); for (int i = 0; i < lightsCount; i++) { diff --git a/src/core.c b/src/core.c index 70dfa7a5..7bd44c81 100644 --- a/src/core.c +++ b/src/core.c @@ -2078,10 +2078,10 @@ static void MouseButtonCallback(GLFWwindow *window, int button, int action, int gestureEvent.position[0] = GetMousePosition(); // Normalize gestureEvent.position[0] for screenWidth and screenHeight - gestureEvent.position[0].x /= (float)GetScreenWidth(); + gestureEvent.position[0].x /= (float)GetScreenWidth(); gestureEvent.position[0].y /= (float)GetScreenHeight(); - - // Gesture data is sent to gestures system for processing + + // Gesture data is sent to gestures system for processing ProcessGestureEvent(gestureEvent); #endif } @@ -2223,10 +2223,10 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd) // Load default font for convenience // NOTE: External function (defined in module: text) LoadDefaultFont(); - + // TODO: GPU assets reload in case of lost focus (lost context) // NOTE: This problem has been solved just unbinding and rebinding context from display - /* + /* if (assetsReloadRequired) { for (int i = 0; i < assetsCount; i++) @@ -2759,9 +2759,9 @@ static void *GamepadThread(void *arg) }; // Read gamepad event - struct js_event gamepadEvent; + struct js_event gamepadEvent; - while (1) + while (1) { for (int i = 0; i < MAX_GAMEPADS; i++) { @@ -2792,8 +2792,8 @@ static void *GamepadThread(void *arg) } } } - } - + } + return NULL; } #endif diff --git a/src/raylib.h b/src/raylib.h index 271c0e42..1ef0a98e 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -349,7 +349,7 @@ typedef struct Camera { Vector3 position; // Camera position Vector3 target; // Camera target it looks-at Vector3 up; // Camera up vector (rotation over its axis) - float fovy; // Field-Of-View apperture in Y (degrees) + float fovy; // Camera field-of-view apperture in Y (degrees) } Camera; // Camera2D type, defines a 2d camera @@ -362,86 +362,84 @@ typedef struct Camera2D { // Bounding box type typedef struct BoundingBox { - Vector3 min; - Vector3 max; + Vector3 min; // minimum vertex box-corner + Vector3 max; // maximum vertex box-corner } BoundingBox; // Vertex data definning a mesh typedef struct Mesh { - int vertexCount; // number of vertices stored in arrays - int triangleCount; // number of triangles stored (indexed or not) - float *vertices; // vertex position (XYZ - 3 components per vertex) (shader-location = 0) - float *texcoords; // vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1) - float *texcoords2; // vertex second texture coordinates (useful for lightmaps) (shader-location = 5) - float *normals; // vertex normals (XYZ - 3 components per vertex) (shader-location = 2) - float *tangents; // vertex tangents (XYZ - 3 components per vertex) (shader-location = 4) - unsigned char *colors; // vertex colors (RGBA - 4 components per vertex) (shader-location = 3) - unsigned short *indices; // vertex indices (in case vertex data comes indexed) - - BoundingBox bounds; // mesh limits defined by min and max points - - unsigned int vaoId; // OpenGL Vertex Array Object id - unsigned int vboId[7]; // OpenGL Vertex Buffer Objects id (7 types of vertex data) + int vertexCount; // number of vertices stored in arrays + int triangleCount; // number of triangles stored (indexed or not) + float *vertices; // vertex position (XYZ - 3 components per vertex) (shader-location = 0) + float *texcoords; // vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1) + float *texcoords2; // vertex second texture coordinates (useful for lightmaps) (shader-location = 5) + float *normals; // vertex normals (XYZ - 3 components per vertex) (shader-location = 2) + float *tangents; // vertex tangents (XYZ - 3 components per vertex) (shader-location = 4) + unsigned char *colors; // vertex colors (RGBA - 4 components per vertex) (shader-location = 3) + unsigned short *indices;// vertex indices (in case vertex data comes indexed) + + unsigned int vaoId; // OpenGL Vertex Array Object id + unsigned int vboId[7]; // OpenGL Vertex Buffer Objects id (7 types of vertex data) } Mesh; // Shader type (generic shader) typedef struct Shader { - unsigned int id; // Shader program id + unsigned int id; // Shader program id // Vertex attributes locations (default locations) - int vertexLoc; // Vertex attribute location point (default-location = 0) - int texcoordLoc; // Texcoord attribute location point (default-location = 1) - int texcoord2Loc; // Texcoord2 attribute location point (default-location = 5) - int normalLoc; // Normal attribute location point (default-location = 2) - int tangentLoc; // Tangent attribute location point (default-location = 4) - int colorLoc; // Color attibute location point (default-location = 3) + int vertexLoc; // Vertex attribute location point (default-location = 0) + int texcoordLoc; // Texcoord attribute location point (default-location = 1) + int texcoord2Loc; // Texcoord2 attribute location point (default-location = 5) + int normalLoc; // Normal attribute location point (default-location = 2) + int tangentLoc; // Tangent attribute location point (default-location = 4) + int colorLoc; // Color attibute location point (default-location = 3) // Uniform locations - int mvpLoc; // ModelView-Projection matrix uniform location point (vertex shader) - int tintColorLoc; // Diffuse color uniform location point (fragment shader) + int mvpLoc; // ModelView-Projection matrix uniform location point (vertex shader) + int tintColorLoc; // Diffuse color uniform location point (fragment shader) // Texture map locations (generic for any kind of map) - int mapTexture0Loc; // Map texture uniform location point (default-texture-unit = 0) - int mapTexture1Loc; // Map texture uniform location point (default-texture-unit = 1) - int mapTexture2Loc; // Map texture uniform location point (default-texture-unit = 2) + int mapTexture0Loc; // Map texture uniform location point (default-texture-unit = 0) + int mapTexture1Loc; // Map texture uniform location point (default-texture-unit = 1) + int mapTexture2Loc; // Map texture uniform location point (default-texture-unit = 2) } Shader; // Material type typedef struct Material { - Shader shader; // Standard shader (supports 3 map textures) + Shader shader; // Standard shader (supports 3 map textures) - Texture2D texDiffuse; // Diffuse texture (binded to shader mapTexture0Loc) - Texture2D texNormal; // Normal texture (binded to shader mapTexture1Loc) - Texture2D texSpecular; // Specular texture (binded to shader mapTexture2Loc) + Texture2D texDiffuse; // Diffuse texture (binded to shader mapTexture0Loc) + Texture2D texNormal; // Normal texture (binded to shader mapTexture1Loc) + Texture2D texSpecular; // Specular texture (binded to shader mapTexture2Loc) - Color colDiffuse; // Diffuse color - Color colAmbient; // Ambient color - Color colSpecular; // Specular color + Color colDiffuse; // Diffuse color + Color colAmbient; // Ambient color + Color colSpecular; // Specular color - float glossiness; // Glossiness level (Ranges from 0 to 1000) + float glossiness; // Glossiness level (Ranges from 0 to 1000) } Material; // Model type typedef struct Model { - Mesh mesh; // Vertex data buffers (RAM and VRAM) - Matrix transform; // Local transform matrix - Material material; // Shader and textures data + Mesh mesh; // Vertex data buffers (RAM and VRAM) + Matrix transform; // Local transform matrix + Material material; // Shader and textures data } Model; // Light type typedef struct LightData { - unsigned int id; // Light id - int type; // Light type: LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT - bool enabled; // Light enabled + unsigned int id; // Light unique id + int type; // Light type: LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT + bool enabled; // Light enabled - Vector3 position; // Light position - Vector3 target; // Light target: LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target) - float radius; // Light attenuation radius light intensity reduced with distance (world distance) + Vector3 position; // Light position + Vector3 target; // Light target: LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target) + float radius; // Light attenuation radius light intensity reduced with distance (world distance) - Color diffuse; // Light diffuse color - float intensity; // Light intensity level + Color diffuse; // Light diffuse color + float intensity; // Light intensity level - float coneAngle; // Light cone max angle: LIGHT_SPOT + float coneAngle; // Light cone max angle: LIGHT_SPOT } LightData, *Light; // Light types diff --git a/src/raymath.h b/src/raymath.h index 59d66e56..2e055e9f 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -73,7 +73,7 @@ //---------------------------------------------------------------------------------- #if defined(RAYMATH_STANDALONE) - // Vector2 type + // Vector2 type typedef struct Vector2 { float x; float y; diff --git a/src/rlgl.c b/src/rlgl.c index 6a2adeb2..89361f46 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -2369,7 +2369,7 @@ static void LoadCompressedTexture(unsigned char *data, int width, int height, in static unsigned int LoadShaderProgram(char *vShaderStr, char *fShaderStr) { unsigned int program = 0; - + #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) GLuint vertexShader; GLuint fragmentShader; diff --git a/src/rlgl.h b/src/rlgl.h index 336f6019..e8e754b4 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -130,51 +130,43 @@ typedef enum { OPENGL_11 = 1, OPENGL_33, OPENGL_ES_20 } GlVersion; COMPRESSED_ASTC_4x4_RGBA, // 8 bpp COMPRESSED_ASTC_8x8_RGBA // 2 bpp } TextureFormat; - - // Bounding box type - typedef struct BoundingBox { - Vector3 min; - Vector3 max; - } BoundingBox; // Vertex data definning a mesh typedef struct Mesh { - int vertexCount; // number of vertices stored in arrays - float *vertices; // vertex position (XYZ - 3 components per vertex) (shader-location = 0) - float *texcoords; // vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1) - float *texcoords2; // vertex second texture coordinates (useful for lightmaps) (shader-location = 5) - float *normals; // vertex normals (XYZ - 3 components per vertex) (shader-location = 2) - float *tangents; // vertex tangents (XYZ - 3 components per vertex) (shader-location = 4) - unsigned char *colors; // vertex colors (RGBA - 4 components per vertex) (shader-location = 3) - unsigned short *indices; // vertex indices (in case vertex data comes indexed) - int triangleCount; // number of triangles stored (indexed or not) - - BoundingBox bounds; // mesh limits defined by min and max points - - unsigned int vaoId; // OpenGL Vertex Array Object id - unsigned int vboId[7]; // OpenGL Vertex Buffer Objects id (7 types of vertex data) + int vertexCount; // number of vertices stored in arrays + int triangleCount; // number of triangles stored (indexed or not) + float *vertices; // vertex position (XYZ - 3 components per vertex) (shader-location = 0) + float *texcoords; // vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1) + float *texcoords2; // vertex second texture coordinates (useful for lightmaps) (shader-location = 5) + float *normals; // vertex normals (XYZ - 3 components per vertex) (shader-location = 2) + float *tangents; // vertex tangents (XYZ - 3 components per vertex) (shader-location = 4) + unsigned char *colors; // vertex colors (RGBA - 4 components per vertex) (shader-location = 3) + unsigned short *indices;// vertex indices (in case vertex data comes indexed) + + unsigned int vaoId; // OpenGL Vertex Array Object id + unsigned int vboId[7]; // OpenGL Vertex Buffer Objects id (7 types of vertex data) } Mesh; // Shader type (generic shader) typedef struct Shader { - unsigned int id; // Shader program id + unsigned int id; // Shader program id // Vertex attributes locations (default locations) - int vertexLoc; // Vertex attribute location point (default-location = 0) - int texcoordLoc; // Texcoord attribute location point (default-location = 1) - int normalLoc; // Normal attribute location point (default-location = 2) - int colorLoc; // Color attibute location point (default-location = 3) - int tangentLoc; // Tangent attribute location point (default-location = 4) - int texcoord2Loc; // Texcoord2 attribute location point (default-location = 5) + int vertexLoc; // Vertex attribute location point (default-location = 0) + int texcoordLoc; // Texcoord attribute location point (default-location = 1) + int normalLoc; // Normal attribute location point (default-location = 2) + int colorLoc; // Color attibute location point (default-location = 3) + int tangentLoc; // Tangent attribute location point (default-location = 4) + int texcoord2Loc; // Texcoord2 attribute location point (default-location = 5) // Uniform locations - int mvpLoc; // ModelView-Projection matrix uniform location point (vertex shader) - int tintColorLoc; // Color uniform location point (fragment shader) + int mvpLoc; // ModelView-Projection matrix uniform location point (vertex shader) + int tintColorLoc; // Color uniform location point (fragment shader) // Texture map locations (generic for any kind of map) - int mapTexture0Loc; // Map texture uniform location point (default-texture-unit = 0) - int mapTexture1Loc; // Map texture uniform location point (default-texture-unit = 1) - int mapTexture2Loc; // Map texture uniform location point (default-texture-unit = 2) + int mapTexture0Loc; // Map texture uniform location point (default-texture-unit = 0) + int mapTexture1Loc; // Map texture uniform location point (default-texture-unit = 1) + int mapTexture2Loc; // Map texture uniform location point (default-texture-unit = 2) } Shader; // Texture2D type @@ -196,35 +188,46 @@ typedef enum { OPENGL_11 = 1, OPENGL_33, OPENGL_ES_20 } GlVersion; // Material type typedef struct Material { - Shader shader; // Standard shader (supports 3 map types: diffuse, normal, specular) + Shader shader; // Standard shader (supports 3 map types: diffuse, normal, specular) - Texture2D texDiffuse; // Diffuse texture - Texture2D texNormal; // Normal texture - Texture2D texSpecular; // Specular texture + Texture2D texDiffuse; // Diffuse texture + Texture2D texNormal; // Normal texture + Texture2D texSpecular; // Specular texture - Color colDiffuse; // Diffuse color - Color colAmbient; // Ambient color - Color colSpecular; // Specular color + Color colDiffuse; // Diffuse color + Color colAmbient; // Ambient color + Color colSpecular; // Specular color - float glossiness; // Glossiness level (Ranges from 0 to 1000) + float glossiness; // Glossiness level (Ranges from 0 to 1000) } Material; + // Camera type, defines a camera position/orientation in 3d space + typedef struct Camera { + Vector3 position; // Camera position + Vector3 target; // Camera target it looks-at + Vector3 up; // Camera up vector (rotation over its axis) + float fovy; // Camera field-of-view apperture in Y (degrees) + } Camera; + // Light type typedef struct LightData { - unsigned int id; // Light id - int type; // Light type: LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT - bool enabled; // Light enabled + unsigned int id; // Light unique id + int type; // Light type: LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT + bool enabled; // Light enabled - Vector3 position; // Light position - Vector3 target; // Light target: LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target) - float radius; // Light attenuation radius light intensity reduced with distance (world distance) + Vector3 position; // Light position + Vector3 target; // Light target: LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target) + float radius; // Light attenuation radius light intensity reduced with distance (world distance) - Color diffuse; // Light diffuse color - float intensity; // Light intensity level + Color diffuse; // Light diffuse color + float intensity; // Light intensity level - float coneAngle; // Light cone max angle: LIGHT_SPOT + float coneAngle; // Light cone max angle: LIGHT_SPOT } LightData, *Light; - + + // Light types + typedef enum { LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT } LightType; + // Color blending modes (pre-defined) typedef enum { BLEND_ALPHA = 0, BLEND_ADDITIVE, BLEND_MULTIPLIED } BlendMode; #endif diff --git a/src/shapes.c b/src/shapes.c index 5b66e5ef..7129ac17 100644 --- a/src/shapes.c +++ b/src/shapes.c @@ -489,7 +489,7 @@ Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2) retRec.height = rec2.height - dyy; } } - + if (rec1.width > rec2.width) { if (retRec.width >= rec2.width) retRec.width = rec2.width; -- cgit v1.2.3 From 90e1ed2b5e54a9b6c69be3dd2b71d1e4f3632c33 Mon Sep 17 00:00:00 2001 From: Joshua Reisenauer Date: Wed, 1 Jun 2016 20:09:00 -0700 Subject: mod player added --- src/audio.c | 85 +++- src/audio.h | 3 +- src/jar_mod.h | 1583 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/raylib.h | 3 +- 4 files changed, 1652 insertions(+), 22 deletions(-) create mode 100644 src/jar_mod.h (limited to 'src/raylib.h') diff --git a/src/audio.c b/src/audio.c index c72b32aa..ceec5577 100644 --- a/src/audio.c +++ b/src/audio.c @@ -56,6 +56,9 @@ #define JAR_XM_IMPLEMENTATION #include "jar_xm.h" // For playing .xm files +#define JAR_MOD_IMPLEMENTATION +#include "jar_mod.h" // For playing .mod files + //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- @@ -95,10 +98,11 @@ typedef struct MixChannel_t { // NOTE: Anything longer than ~10 seconds should be streamed into a mix channel... typedef struct Music { stb_vorbis *stream; - jar_xm_context_t *chipctx; // Stores jar_xm mixc + jar_xm_context_t *xmctx; // Stores jar_xm mixc, XM chiptune context + modcontext modctx; // Stores mod chiptune context MixChannel_t *mixc; // mix channel - int totalSamplesLeft; + unsigned int totalSamplesLeft; float totalLengthSeconds; bool loop; bool chipTune; // True if chiptune is loaded @@ -399,6 +403,8 @@ void CloseRawAudioContext(RawAudioContext ctx) CloseMixChannel(mixChannelsActive_g[ctx]); } +// if 0 is returned, the buffers are still full and you need to keep trying with same data until a number is returned. +// any other number returned is the number that was processed and passed into buffer. int BufferRawAudioContext(RawAudioContext ctx, void *data, unsigned short numberElements) { int numBuffered = 0; @@ -767,7 +773,7 @@ int PlayMusicStream(int musicIndex, char *fileName) { int mixIndex; - if(currentMusic[musicIndex].stream || currentMusic[musicIndex].chipctx) return 1; // error + if(currentMusic[musicIndex].stream || currentMusic[musicIndex].xmctx) return 1; // error for(mixIndex = 0; mixIndex < MAX_MIX_CHANNELS; mixIndex++) // find empty mix channel slot { @@ -798,7 +804,7 @@ int PlayMusicStream(int musicIndex, char *fileName) musicEnabled_g = true; - currentMusic[musicIndex].totalSamplesLeft = stb_vorbis_stream_length_in_samples(currentMusic[musicIndex].stream) * info.channels; + currentMusic[musicIndex].totalSamplesLeft = (unsigned int)stb_vorbis_stream_length_in_samples(currentMusic[musicIndex].stream) * info.channels; currentMusic[musicIndex].totalLengthSeconds = stb_vorbis_stream_length_in_seconds(currentMusic[musicIndex].stream); if (info.channels == 2){ @@ -815,12 +821,12 @@ int PlayMusicStream(int musicIndex, char *fileName) else if (strcmp(GetExtension(fileName),"xm") == 0) { // only stereo is supported for xm - if(!jar_xm_create_context_from_file(¤tMusic[musicIndex].chipctx, 48000, fileName)) + if(!jar_xm_create_context_from_file(¤tMusic[musicIndex].xmctx, 48000, fileName)) { currentMusic[musicIndex].chipTune = true; currentMusic[musicIndex].loop = true; - jar_xm_set_max_loop_count(currentMusic[musicIndex].chipctx, 0); // infinite number of loops - currentMusic[musicIndex].totalSamplesLeft = jar_xm_get_remaining_samples(currentMusic[musicIndex].chipctx); + jar_xm_set_max_loop_count(currentMusic[musicIndex].xmctx, 0); // infinite number of loops + currentMusic[musicIndex].totalSamplesLeft = (unsigned int)jar_xm_get_remaining_samples(currentMusic[musicIndex].xmctx); currentMusic[musicIndex].totalLengthSeconds = ((float)currentMusic[musicIndex].totalSamplesLeft) / 48000.f; musicEnabled_g = true; @@ -837,10 +843,34 @@ int PlayMusicStream(int musicIndex, char *fileName) return 6; // error } } + else if (strcmp(GetExtension(fileName),"mod") == 0) + { + jar_mod_init(¤tMusic[musicIndex].modctx); + if(jar_mod_load_file(¤tMusic[musicIndex].modctx, fileName)) + { + currentMusic[musicIndex].chipTune = true; + currentMusic[musicIndex].loop = true; + currentMusic[musicIndex].totalSamplesLeft = (unsigned int)jar_mod_max_samples(¤tMusic[musicIndex].modctx); + currentMusic[musicIndex].totalLengthSeconds = ((float)currentMusic[musicIndex].totalSamplesLeft) / 48000.f; + musicEnabled_g = true; + + TraceLog(INFO, "[%s] MOD number of samples: %i", fileName, currentMusic[musicIndex].totalSamplesLeft); + TraceLog(INFO, "[%s] MOD track length: %11.6f sec", fileName, currentMusic[musicIndex].totalLengthSeconds); + + currentMusic[musicIndex].mixc = InitMixChannel(48000, mixIndex, 2, false); + if(!currentMusic[musicIndex].mixc) return 7; // error + currentMusic[musicIndex].mixc->playing = true; + } + else + { + TraceLog(WARNING, "[%s] MOD file could not be opened", fileName); + return 8; // error + } + } else { TraceLog(WARNING, "[%s] Music extension not recognized, it can't be loaded", fileName); - return 7; // error + return 9; // error } return 0; // normal return } @@ -852,9 +882,14 @@ void StopMusicStream(int index) { CloseMixChannel(currentMusic[index].mixc); - if (currentMusic[index].chipTune) + if (currentMusic[index].chipTune && currentMusic[index].xmctx) { - jar_xm_free_context(currentMusic[index].chipctx); + jar_xm_free_context(currentMusic[index].xmctx); + currentMusic[index].xmctx = 0; + } + else if(currentMusic[index].chipTune && currentMusic[index].modctx.mod_loaded) + { + jar_mod_unload(¤tMusic[index].modctx); } else { @@ -862,10 +897,10 @@ void StopMusicStream(int index) } if(!getMusicStreamCount()) musicEnabled_g = false; - if(currentMusic[index].stream || currentMusic[index].chipctx) + if(currentMusic[index].stream || currentMusic[index].xmctx) { currentMusic[index].stream = NULL; - currentMusic[index].chipctx = NULL; + currentMusic[index].xmctx = NULL; } } } @@ -937,13 +972,13 @@ void SetMusicPitch(int index, float pitch) } } -// Get current music time length (in seconds) +// Get music time length (in seconds) float GetMusicTimeLength(int index) { float totalSeconds; if (currentMusic[index].chipTune) { - totalSeconds = currentMusic[index].totalLengthSeconds; + totalSeconds = (float)currentMusic[index].totalLengthSeconds; } else { @@ -959,11 +994,16 @@ float GetMusicTimePlayed(int index) float secondsPlayed = 0.0f; if(index < MAX_MUSIC_STREAMS && currentMusic[index].mixc) { - if (currentMusic[index].chipTune) + if (currentMusic[index].chipTune && currentMusic[index].xmctx) { uint64_t samples; - jar_xm_get_position(currentMusic[index].chipctx, NULL, NULL, NULL, &samples); - secondsPlayed = (float)samples / (48000 * currentMusic[index].mixc->channels); // Not sure if this is the correct value + jar_xm_get_position(currentMusic[index].xmctx, NULL, NULL, NULL, &samples); + secondsPlayed = (float)samples / (48000.f * currentMusic[index].mixc->channels); // Not sure if this is the correct value + } + else if(currentMusic[index].chipTune && currentMusic[index].modctx.mod_loaded) + { + long numsamp = jar_mod_current_samples(¤tMusic[index].modctx); + secondsPlayed = (float)numsamp / (48000.f); } else { @@ -984,7 +1024,7 @@ float GetMusicTimePlayed(int index) static bool BufferMusicStream(int index, int numBuffers) { short pcm[MUSIC_BUFFER_SIZE_SHORT]; - float pcmf[MUSIC_BUFFER_SIZE_FLOAT]; + //float pcmf[MUSIC_BUFFER_SIZE_FLOAT]; int size = 0; // Total size of data steamed in L+R samples for xm floats, individual L or R for ogg shorts bool active = true; // We can get more data from stream (not finished) @@ -998,9 +1038,13 @@ static bool BufferMusicStream(int index, int numBuffers) for(int x=0; x free.fr> +// Adapted to jar_mod by: Joshua Adam Reisenauer +// This program is free software. It comes without any warranty, to the +// extent permitted by applicable law. You can redistribute it and/or +// modify it under the terms of the Do What The Fuck You Want To Public +// License, Version 2, as published by Sam Hocevar. See +// http://sam.zoy.org/wtfpl/COPYING for more details. +/////////////////////////////////////////////////////////////////////////////////// +// HxCMOD Core API: +// ------------------------------------------- +// int jar_mod_init(modcontext * modctx) +// +// - Initialize the modcontext buffer. Must be called before doing anything else. +// Return 1 if success. 0 in case of error. +// ------------------------------------------- +// mulong jar_mod_load_file(modcontext * modctx, char* filename) +// +// - "Load" a MOD from file, context must already be initialized. +// Return size of file in bytes. +// ------------------------------------------- +// void jar_mod_fillbuffer( modcontext * modctx, unsigned short * outbuffer, unsigned long nbsample, jar_mod_tracker_buffer_state * trkbuf ) +// +// - Generate and return the next samples chunk to outbuffer. +// nbsample specify the number of stereo 16bits samples you want. +// The output format is by default signed 48000Hz 16-bit Stereo PCM samples, otherwise it is changed with jar_mod_setcfg(). +// The output buffer size in bytes must be equal to ( nbsample * 2 * channels ). +// The optional trkbuf parameter can be used to get detailed status of the player. Put NULL/0 is unused. +// ------------------------------------------- +// void jar_mod_unload( modcontext * modctx ) +// - "Unload" / clear the player status. +// ------------------------------------------- +/////////////////////////////////////////////////////////////////////////////////// + + +#ifndef INCLUDE_JAR_MOD_H +#define INCLUDE_JAR_MOD_H + +#include +#include +#include + + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// Basic type +typedef unsigned char muchar; +typedef unsigned short muint; +typedef short mint; +typedef unsigned long mulong; + +#define NUMMAXCHANNELS 32 +#define MAXNOTES 12*12 +#define DEFAULT_SAMPLE_RATE 48000 +// +// MOD file structures +// + +#pragma pack(1) + +typedef struct { + muchar name[22]; + muint length; + muchar finetune; + muchar volume; + muint reppnt; + muint replen; +} sample; + +typedef struct { + muchar sampperiod; + muchar period; + muchar sampeffect; + muchar effect; +} note; + +typedef struct { + muchar title[20]; + sample samples[31]; + muchar length; // length of tablepos + muchar protracker; + muchar patterntable[128]; + muchar signature[4]; + muchar speed; +} module; + +#pragma pack() + +// +// HxCMod Internal structures +// +typedef struct { + char* sampdata; + muint sampnum; + muint length; + muint reppnt; + muint replen; + mulong samppos; + muint period; + muchar volume; + mulong ticks; + muchar effect; + muchar parameffect; + muint effect_code; + mint decalperiod; + mint portaspeed; + mint portaperiod; + mint vibraperiod; + mint Arpperiods[3]; + muchar ArpIndex; + mint oldk; + muchar volumeslide; + muchar vibraparam; + muchar vibrapointeur; + muchar finetune; + muchar cut_param; + muint patternloopcnt; + muint patternloopstartpoint; +} channel; + +typedef struct { + module song; + char* sampledata[31]; + note* patterndata[128]; + + mulong playrate; + muint tablepos; + muint patternpos; + muint patterndelay; + muint jump_loop_effect; + muchar bpm; + mulong patternticks; + mulong patterntickse; + mulong patternticksaim; + mulong sampleticksconst; + mulong samplenb; + channel channels[NUMMAXCHANNELS]; + muint number_of_channels; + muint fullperiod[MAXNOTES * 8]; + muint mod_loaded; + mint last_r_sample; + mint last_l_sample; + mint stereo; + mint stereo_separation; + mint bits; + mint filter; + + muchar *modfile; // the raw mod file + mulong modfilesize; + muint loopcount; +} modcontext; + +// +// Player states structures +// +typedef struct track_state_ +{ + unsigned char instrument_number; + unsigned short cur_period; + unsigned char cur_volume; + unsigned short cur_effect; + unsigned short cur_parameffect; +}track_state; + +typedef struct tracker_state_ +{ + int number_of_tracks; + int bpm; + int speed; + int cur_pattern; + int cur_pattern_pos; + int cur_pattern_table_pos; + unsigned int buf_index; + track_state tracks[32]; +}tracker_state; + +typedef struct tracker_state_instrument_ +{ + char name[22]; + int active; +}tracker_state_instrument; + +typedef struct jar_mod_tracker_buffer_state_ +{ + int nb_max_of_state; + int nb_of_state; + int cur_rd_index; + int sample_step; + char name[64]; + tracker_state_instrument instruments[31]; + tracker_state * track_state_buf; +}jar_mod_tracker_buffer_state; + + + +bool jar_mod_init(modcontext * modctx); +bool jar_mod_setcfg(modcontext * modctx, int samplerate, int bits, int stereo, int stereo_separation, int filter); +void jar_mod_fillbuffer(modcontext * modctx, short * outbuffer, unsigned long nbsample, jar_mod_tracker_buffer_state * trkbuf); +void jar_mod_unload(modcontext * modctx); +mulong jar_mod_load_file(modcontext * modctx, char* filename); +mulong jar_mod_current_samples(modcontext * modctx); +mulong jar_mod_max_samples(modcontext * modctx); +void jar_mod_seek_start(modcontext * ctx); + +#ifdef __cplusplus +} +#endif +//-------------------------------------------------------------------- + + + +//------------------------------------------------------------------------------- +#ifdef JAR_MOD_IMPLEMENTATION + +// Effects list +#define EFFECT_ARPEGGIO 0x0 // Supported +#define EFFECT_PORTAMENTO_UP 0x1 // Supported +#define EFFECT_PORTAMENTO_DOWN 0x2 // Supported +#define EFFECT_TONE_PORTAMENTO 0x3 // Supported +#define EFFECT_VIBRATO 0x4 // Supported +#define EFFECT_VOLSLIDE_TONEPORTA 0x5 // Supported +#define EFFECT_VOLSLIDE_VIBRATO 0x6 // Supported +#define EFFECT_VOLSLIDE_TREMOLO 0x7 // - TO BE DONE - +#define EFFECT_SET_PANNING 0x8 // - TO BE DONE - +#define EFFECT_SET_OFFSET 0x9 // Supported +#define EFFECT_VOLUME_SLIDE 0xA // Supported +#define EFFECT_JUMP_POSITION 0xB // Supported +#define EFFECT_SET_VOLUME 0xC // Supported +#define EFFECT_PATTERN_BREAK 0xD // Supported + +#define EFFECT_EXTENDED 0xE +#define EFFECT_E_FINE_PORTA_UP 0x1 // Supported +#define EFFECT_E_FINE_PORTA_DOWN 0x2 // Supported +#define EFFECT_E_GLISSANDO_CTRL 0x3 // - TO BE DONE - +#define EFFECT_E_VIBRATO_WAVEFORM 0x4 // - TO BE DONE - +#define EFFECT_E_SET_FINETUNE 0x5 // - TO BE DONE - +#define EFFECT_E_PATTERN_LOOP 0x6 // Supported +#define EFFECT_E_TREMOLO_WAVEFORM 0x7 // - TO BE DONE - +#define EFFECT_E_SET_PANNING_2 0x8 // - TO BE DONE - +#define EFFECT_E_RETRIGGER_NOTE 0x9 // - TO BE DONE - +#define EFFECT_E_FINE_VOLSLIDE_UP 0xA // Supported +#define EFFECT_E_FINE_VOLSLIDE_DOWN 0xB // Supported +#define EFFECT_E_NOTE_CUT 0xC // Supported +#define EFFECT_E_NOTE_DELAY 0xD // - TO BE DONE - +#define EFFECT_E_PATTERN_DELAY 0xE // Supported +#define EFFECT_E_INVERT_LOOP 0xF // - TO BE DONE - +#define EFFECT_SET_SPEED 0xF0 // Supported +#define EFFECT_SET_TEMPO 0xF2 // Supported + +#define PERIOD_TABLE_LENGTH MAXNOTES +#define FULL_PERIOD_TABLE_LENGTH ( PERIOD_TABLE_LENGTH * 8 ) + +static const short periodtable[]= +{ + 27392, 25856, 24384, 23040, 21696, 20480, 19328, 18240, 17216, 16256, 15360, 14496, + 13696, 12928, 12192, 11520, 10848, 10240, 9664, 9120, 8606, 8128, 7680, 7248, + 6848, 6464, 6096, 5760, 5424, 5120, 4832, 4560, 4304, 4064, 3840, 3624, + 3424, 3232, 3048, 2880, 2712, 2560, 2416, 2280, 2152, 2032, 1920, 1812, + 1712, 1616, 1524, 1440, 1356, 1280, 1208, 1140, 1076, 1016, 960, 906, + 856, 808, 762, 720, 678, 640, 604, 570, 538, 508, 480, 453, + 428, 404, 381, 360, 339, 320, 302, 285, 269, 254, 240, 226, + 214, 202, 190, 180, 170, 160, 151, 143, 135, 127, 120, 113, + 107, 101, 95, 90, 85, 80, 75, 71, 67, 63, 60, 56, + 53, 50, 47, 45, 42, 40, 37, 35, 33, 31, 30, 28, + 27, 25, 24, 22, 21, 20, 19, 18, 17, 16, 15, 14, + 13, 13, 12, 11, 11, 10, 9, 9, 8, 8, 7, 7 +}; + +static const short sintable[]={ + 0, 24, 49, 74, 97, 120, 141,161, + 180, 197, 212, 224, 235, 244, 250,253, + 255, 253, 250, 244, 235, 224, 212,197, + 180, 161, 141, 120, 97, 74, 49, 24 +}; + +typedef struct modtype_ +{ + unsigned char signature[5]; + int numberofchannels; +}modtype; + +modtype modlist[]= +{ + { "M!K!",4}, + { "M.K.",4}, + { "FLT4",4}, + { "FLT8",8}, + { "4CHN",4}, + { "6CHN",6}, + { "8CHN",8}, + { "10CH",10}, + { "12CH",12}, + { "14CH",14}, + { "16CH",16}, + { "18CH",18}, + { "20CH",20}, + { "22CH",22}, + { "24CH",24}, + { "26CH",26}, + { "28CH",28}, + { "30CH",30}, + { "32CH",32}, + { "",0} +}; + +/////////////////////////////////////////////////////////////////////////////////// + +static void memcopy( void * dest, void *source, unsigned long size ) +{ + unsigned long i; + unsigned char * d,*s; + + d=(unsigned char*)dest; + s=(unsigned char*)source; + for(i=0;i= mod->fullperiod[i]) + { + return i; + } + } + + return MAXNOTES; +} + +static void worknote( note * nptr, channel * cptr, char t, modcontext * mod ) +{ + muint sample, period, effect, operiod; + muint curnote, arpnote; + + sample = (nptr->sampperiod & 0xF0) | (nptr->sampeffect >> 4); + period = ((nptr->sampperiod & 0xF) << 8) | nptr->period; + effect = ((nptr->sampeffect & 0xF) << 8) | nptr->effect; + + operiod = cptr->period; + + if ( period || sample ) + { + if( sample && sample < 32 ) + { + cptr->sampnum = sample - 1; + } + + if( period || sample ) + { + cptr->sampdata = (char *) mod->sampledata[cptr->sampnum]; + cptr->length = mod->song.samples[cptr->sampnum].length; + cptr->reppnt = mod->song.samples[cptr->sampnum].reppnt; + cptr->replen = mod->song.samples[cptr->sampnum].replen; + + cptr->finetune = (mod->song.samples[cptr->sampnum].finetune)&0xF; + + if(effect>>8!=4 && effect>>8!=6) + { + cptr->vibraperiod=0; + cptr->vibrapointeur=0; + } + } + + if( (sample != 0) && ( (effect>>8) != EFFECT_VOLSLIDE_TONEPORTA ) ) + { + cptr->volume = mod->song.samples[cptr->sampnum].volume; + cptr->volumeslide = 0; + } + + if( ( (effect>>8) != EFFECT_TONE_PORTAMENTO && (effect>>8)!=EFFECT_VOLSLIDE_TONEPORTA) ) + { + if (period!=0) + cptr->samppos = 0; + } + + cptr->decalperiod = 0; + if( period ) + { + if(cptr->finetune) + { + if( cptr->finetune <= 7 ) + { + period = mod->fullperiod[getnote(mod,period,0) + cptr->finetune]; + } + else + { + period = mod->fullperiod[getnote(mod,period,0) - (16 - (cptr->finetune)) ]; + } + } + + cptr->period = period; + } + + } + + cptr->effect = 0; + cptr->parameffect = 0; + cptr->effect_code = effect; + + switch (effect >> 8) + { + case EFFECT_ARPEGGIO: + /* + [0]: Arpeggio + Where [0][x][y] means "play note, note+x semitones, note+y + semitones, then return to original note". The fluctuations are + carried out evenly spaced in one pattern division. They are usually + used to simulate chords, but this doesn't work too well. They are + also used to produce heavy vibrato. A major chord is when x=4, y=7. + A minor chord is when x=3, y=7. + */ + + if(effect&0xff) + { + cptr->effect = EFFECT_ARPEGGIO; + cptr->parameffect = effect&0xff; + + cptr->ArpIndex = 0; + + curnote = getnote(mod,cptr->period,cptr->finetune); + + cptr->Arpperiods[0] = cptr->period; + + arpnote = curnote + (((cptr->parameffect>>4)&0xF)*8); + if( arpnote >= FULL_PERIOD_TABLE_LENGTH ) + arpnote = FULL_PERIOD_TABLE_LENGTH - 1; + + cptr->Arpperiods[1] = mod->fullperiod[arpnote]; + + arpnote = curnote + (((cptr->parameffect)&0xF)*8); + if( arpnote >= FULL_PERIOD_TABLE_LENGTH ) + arpnote = FULL_PERIOD_TABLE_LENGTH - 1; + + cptr->Arpperiods[2] = mod->fullperiod[arpnote]; + } + break; + + case EFFECT_PORTAMENTO_UP: + /* + [1]: Slide up + Where [1][x][y] means "smoothly decrease the period of current + sample by x*16+y after each tick in the division". The + ticks/division are set with the 'set speed' effect (see below). If + the period of the note being played is z, then the final period + will be z - (x*16 + y)*(ticks - 1). As the slide rate depends on + the speed, changing the speed will change the slide. You cannot + slide beyond the note B3 (period 113). + */ + + cptr->effect = EFFECT_PORTAMENTO_UP; + cptr->parameffect = effect&0xff; + break; + + case EFFECT_PORTAMENTO_DOWN: + /* + [2]: Slide down + Where [2][x][y] means "smoothly increase the period of current + sample by x*16+y after each tick in the division". Similar to [1], + but lowers the pitch. You cannot slide beyond the note C1 (period + 856). + */ + + cptr->effect = EFFECT_PORTAMENTO_DOWN; + cptr->parameffect = effect&0xff; + break; + + case EFFECT_TONE_PORTAMENTO: + /* + [3]: Slide to note + Where [3][x][y] means "smoothly change the period of current sample + by x*16+y after each tick in the division, never sliding beyond + current period". The period-length in this channel's division is a + parameter to this effect, and hence is not played. Sliding to a + note is similar to effects [1] and [2], but the slide will not go + beyond the given period, and the direction is implied by that + period. If x and y are both 0, then the old slide will continue. + */ + + cptr->effect = EFFECT_TONE_PORTAMENTO; + if( (effect&0xff) != 0 ) + { + cptr->portaspeed = (short)(effect&0xff); + } + + if(period!=0) + { + cptr->portaperiod = period; + cptr->period = operiod; + } + break; + + case EFFECT_VIBRATO: + /* + [4]: Vibrato + Where [4][x][y] means "oscillate the sample pitch using a + particular waveform with amplitude y/16 semitones, such that (x * + ticks)/64 cycles occur in the division". The waveform is set using + effect [14][4]. By placing vibrato effects on consecutive + divisions, the vibrato effect can be maintained. If either x or y + are 0, then the old vibrato values will be used. + */ + + cptr->effect = EFFECT_VIBRATO; + if( ( effect & 0x0F ) != 0 ) // Depth continue or change ? + cptr->vibraparam = (cptr->vibraparam & 0xF0) | ( effect & 0x0F ); + if( ( effect & 0xF0 ) != 0 ) // Speed continue or change ? + cptr->vibraparam = (cptr->vibraparam & 0x0F) | ( effect & 0xF0 ); + + break; + + case EFFECT_VOLSLIDE_TONEPORTA: + /* + [5]: Continue 'Slide to note', but also do Volume slide + Where [5][x][y] means "either slide the volume up x*(ticks - 1) or + slide the volume down y*(ticks - 1), at the same time as continuing + the last 'Slide to note'". It is illegal for both x and y to be + non-zero. You cannot slide outside the volume range 0..64. The + period-length in this channel's division is a parameter to this + effect, and hence is not played. + */ + + if( period != 0 ) + { + cptr->portaperiod = period; + cptr->period = operiod; + } + + cptr->effect = EFFECT_VOLSLIDE_TONEPORTA; + if( ( effect & 0xFF ) != 0 ) + cptr->volumeslide = ( effect & 0xFF ); + + break; + + case EFFECT_VOLSLIDE_VIBRATO: + /* + [6]: Continue 'Vibrato', but also do Volume slide + Where [6][x][y] means "either slide the volume up x*(ticks - 1) or + slide the volume down y*(ticks - 1), at the same time as continuing + the last 'Vibrato'". It is illegal for both x and y to be non-zero. + You cannot slide outside the volume range 0..64. + */ + + cptr->effect = EFFECT_VOLSLIDE_VIBRATO; + if( (effect & 0xFF) != 0 ) + cptr->volumeslide = (effect & 0xFF); + break; + + case EFFECT_SET_OFFSET: + /* + [9]: Set sample offset + Where [9][x][y] means "play the sample from offset x*4096 + y*256". + The offset is measured in words. If no sample is given, yet one is + still playing on this channel, it should be retriggered to the new + offset using the current volume. + */ + + cptr->samppos = ((effect>>4) * 4096) + ((effect&0xF)*256); + + break; + + case EFFECT_VOLUME_SLIDE: + /* + [10]: Volume slide + Where [10][x][y] means "either slide the volume up x*(ticks - 1) or + slide the volume down y*(ticks - 1)". If both x and y are non-zero, + then the y value is ignored (assumed to be 0). You cannot slide + outside the volume range 0..64. + */ + + cptr->effect = EFFECT_VOLUME_SLIDE; + cptr->volumeslide = (effect & 0xFF); + break; + + case EFFECT_JUMP_POSITION: + /* + [11]: Position Jump + Where [11][x][y] means "stop the pattern after this division, and + continue the song at song-position x*16+y". This shifts the + 'pattern-cursor' in the pattern table (see above). Legal values for + x*16+y are from 0 to 127. + */ + + mod->tablepos = (effect & 0xFF); + if(mod->tablepos >= mod->song.length) + { + mod->tablepos = 0; + } + mod->patternpos = 0; + mod->jump_loop_effect = 1; + + break; + + case EFFECT_SET_VOLUME: + /* + [12]: Set volume + Where [12][x][y] means "set current sample's volume to x*16+y". + Legal volumes are 0..64. + */ + + cptr->volume = (effect & 0xFF); + break; + + case EFFECT_PATTERN_BREAK: + /* + [13]: Pattern Break + Where [13][x][y] means "stop the pattern after this division, and + continue the song at the next pattern at division x*10+y" (the 10 + is not a typo). Legal divisions are from 0 to 63 (note Protracker + exception above). + */ + + mod->patternpos = ( ((effect>>4)&0xF)*10 + (effect&0xF) ) * mod->number_of_channels; + mod->jump_loop_effect = 1; + mod->tablepos++; + if(mod->tablepos >= mod->song.length) + { + mod->tablepos = 0; + } + + break; + + case EFFECT_EXTENDED: + switch( (effect>>4) & 0xF ) + { + case EFFECT_E_FINE_PORTA_UP: + /* + [14][1]: Fineslide up + Where [14][1][x] means "decrement the period of the current sample + by x". The incrementing takes place at the beginning of the + division, and hence there is no actual sliding. You cannot slide + beyond the note B3 (period 113). + */ + + cptr->period -= (effect & 0xF); + if( cptr->period < 113 ) + cptr->period = 113; + break; + + case EFFECT_E_FINE_PORTA_DOWN: + /* + [14][2]: Fineslide down + Where [14][2][x] means "increment the period of the current sample + by x". Similar to [14][1] but shifts the pitch down. You cannot + slide beyond the note C1 (period 856). + */ + + cptr->period += (effect & 0xF); + if( cptr->period > 856 ) + cptr->period = 856; + break; + + case EFFECT_E_FINE_VOLSLIDE_UP: + /* + [14][10]: Fine volume slide up + Where [14][10][x] means "increment the volume of the current sample + by x". The incrementing takes place at the beginning of the + division, and hence there is no sliding. You cannot slide beyond + volume 64. + */ + + cptr->volume += (effect & 0xF); + if( cptr->volume>64 ) + cptr->volume = 64; + break; + + case EFFECT_E_FINE_VOLSLIDE_DOWN: + /* + [14][11]: Fine volume slide down + Where [14][11][x] means "decrement the volume of the current sample + by x". Similar to [14][10] but lowers volume. You cannot slide + beyond volume 0. + */ + + cptr->volume -= (effect & 0xF); + if( cptr->volume > 200 ) + cptr->volume = 0; + break; + + case EFFECT_E_PATTERN_LOOP: + /* + [14][6]: Loop pattern + Where [14][6][x] means "set the start of a loop to this division if + x is 0, otherwise after this division, jump back to the start of a + loop and play it another x times before continuing". If the start + of the loop was not set, it will default to the start of the + current pattern. Hence 'loop pattern' cannot be performed across + multiple patterns. Note that loops do not support nesting, and you + may generate an infinite loop if you try to nest 'loop pattern's. + */ + + if( effect & 0xF ) + { + if( cptr->patternloopcnt ) + { + cptr->patternloopcnt--; + if( cptr->patternloopcnt ) + { + mod->patternpos = cptr->patternloopstartpoint; + mod->jump_loop_effect = 1; + } + else + { + cptr->patternloopstartpoint = mod->patternpos ; + } + } + else + { + cptr->patternloopcnt = (effect & 0xF); + mod->patternpos = cptr->patternloopstartpoint; + mod->jump_loop_effect = 1; + } + } + else // Start point + { + cptr->patternloopstartpoint = mod->patternpos; + } + + break; + + case EFFECT_E_PATTERN_DELAY: + /* + [14][14]: Delay pattern + Where [14][14][x] means "after this division there will be a delay + equivalent to the time taken to play x divisions after which the + pattern will be resumed". The delay only relates to the + interpreting of new divisions, and all effects and previous notes + continue during delay. + */ + + mod->patterndelay = (effect & 0xF); + break; + + case EFFECT_E_NOTE_CUT: + /* + [14][12]: Cut sample + Where [14][12][x] means "after the current sample has been played + for x ticks in this division, its volume will be set to 0". This + implies that if x is 0, then you will not hear any of the sample. + If you wish to insert "silence" in a pattern, it is better to use a + "silence"-sample (see above) due to the lack of proper support for + this effect. + */ + cptr->effect = EFFECT_E_NOTE_CUT; + cptr->cut_param = (effect & 0xF); + if(!cptr->cut_param) + cptr->volume = 0; + break; + + default: + + break; + } + break; + + case 0xF: + /* + [15]: Set speed + Where [15][x][y] means "set speed to x*16+y". Though it is nowhere + near that simple. Let z = x*16+y. Depending on what values z takes, + different units of speed are set, there being two: ticks/division + and beats/minute (though this one is only a label and not strictly + true). If z=0, then what should technically happen is that the + module stops, but in practice it is treated as if z=1, because + there is already a method for stopping the module (running out of + patterns). If z<=32, then it means "set ticks/division to z" + otherwise it means "set beats/minute to z" (convention says that + this should read "If z<32.." but there are some composers out there + that defy conventions). Default values are 6 ticks/division, and + 125 beats/minute (4 divisions = 1 beat). The beats/minute tag is + only meaningful for 6 ticks/division. To get a more accurate view + of how things work, use the following formula: + 24 * beats/minute + divisions/minute = ----------------- + ticks/division + Hence divisions/minute range from 24.75 to 6120, eg. to get a value + of 2000 divisions/minute use 3 ticks/division and 250 beats/minute. + If multiple "set speed" effects are performed in a single division, + the ones on higher-numbered channels take precedence over the ones + on lower-numbered channels. This effect has a large number of + different implementations, but the one described here has the + widest usage. + */ + + if( (effect&0xFF) < 0x21 ) + { + if( effect&0xFF ) + { + mod->song.speed = effect&0xFF; + mod->patternticksaim = (long)mod->song.speed * ((mod->playrate * 5 ) / (((long)2 * (long)mod->bpm))); + } + } + + if( (effect&0xFF) >= 0x21 ) + { + /// HZ = 2 * BPM / 5 + mod->bpm = effect&0xFF; + mod->patternticksaim = (long)mod->song.speed * ((mod->playrate * 5 ) / (((long)2 * (long)mod->bpm))); + } + + break; + + default: + // Unsupported effect + break; + + } + +} + +static void workeffect( note * nptr, channel * cptr ) +{ + switch(cptr->effect) + { + case EFFECT_ARPEGGIO: + + if( cptr->parameffect ) + { + cptr->decalperiod = cptr->period - cptr->Arpperiods[cptr->ArpIndex]; + + cptr->ArpIndex++; + if( cptr->ArpIndex>2 ) + cptr->ArpIndex = 0; + } + break; + + case EFFECT_PORTAMENTO_UP: + + if(cptr->period) + { + cptr->period -= cptr->parameffect; + + if( cptr->period < 113 || cptr->period > 20000 ) + cptr->period = 113; + } + + break; + + case EFFECT_PORTAMENTO_DOWN: + + if(cptr->period) + { + cptr->period += cptr->parameffect; + + if( cptr->period > 20000 ) + cptr->period = 20000; + } + + break; + + case EFFECT_VOLSLIDE_TONEPORTA: + case EFFECT_TONE_PORTAMENTO: + + if( cptr->period && ( cptr->period != cptr->portaperiod ) && cptr->portaperiod ) + { + if( cptr->period > cptr->portaperiod ) + { + if( cptr->period - cptr->portaperiod >= cptr->portaspeed ) + { + cptr->period -= cptr->portaspeed; + } + else + { + cptr->period = cptr->portaperiod; + } + } + else + { + if( cptr->portaperiod - cptr->period >= cptr->portaspeed ) + { + cptr->period += cptr->portaspeed; + } + else + { + cptr->period = cptr->portaperiod; + } + } + + if( cptr->period == cptr->portaperiod ) + { + // If the slide is over, don't let it to be retriggered. + cptr->portaperiod = 0; + } + } + + if( cptr->effect == EFFECT_VOLSLIDE_TONEPORTA ) + { + if( cptr->volumeslide > 0x0F ) + { + cptr->volume = cptr->volume + (cptr->volumeslide>>4); + + if(cptr->volume>63) + cptr->volume = 63; + } + else + { + cptr->volume = cptr->volume - (cptr->volumeslide); + + if(cptr->volume>63) + cptr->volume=0; + } + } + break; + + case EFFECT_VOLSLIDE_VIBRATO: + case EFFECT_VIBRATO: + + cptr->vibraperiod = ( (cptr->vibraparam&0xF) * sintable[cptr->vibrapointeur&0x1F] )>>7; + + if( cptr->vibrapointeur > 31 ) + cptr->vibraperiod = -cptr->vibraperiod; + + cptr->vibrapointeur = (cptr->vibrapointeur+(((cptr->vibraparam>>4))&0xf)) & 0x3F; + + if( cptr->effect == EFFECT_VOLSLIDE_VIBRATO ) + { + if( cptr->volumeslide > 0xF ) + { + cptr->volume = cptr->volume+(cptr->volumeslide>>4); + + if( cptr->volume > 64 ) + cptr->volume = 64; + } + else + { + cptr->volume = cptr->volume - cptr->volumeslide; + + if( cptr->volume > 64 ) + cptr->volume = 0; + } + } + + break; + + case EFFECT_VOLUME_SLIDE: + + if( cptr->volumeslide > 0xF ) + { + cptr->volume += (cptr->volumeslide>>4); + + if( cptr->volume > 64 ) + cptr->volume = 64; + } + else + { + cptr->volume -= (cptr->volumeslide&0xf); + + if( cptr->volume > 64 ) + cptr->volume = 0; + } + break; + + case EFFECT_E_NOTE_CUT: + if(cptr->cut_param) + cptr->cut_param--; + + if(!cptr->cut_param) + cptr->volume = 0; + break; + + default: + break; + + } + +} + +/////////////////////////////////////////////////////////////////////////////////// +bool jar_mod_init(modcontext * modctx) +{ + muint i,j; + + if( modctx ) + { + memclear(modctx,0,sizeof(modcontext)); + modctx->playrate = DEFAULT_SAMPLE_RATE; + modctx->stereo = 1; + modctx->stereo_separation = 1; + modctx->bits = 16; + modctx->filter = 1; + modctx->loopcount = 0; + + for(i=0;ifullperiod[(i*8) + j] = periodtable[i] - ((( periodtable[i] - periodtable[i+1] ) / 8) * j); + } + } + + return 1; + } + + return 0; +} + +bool jar_mod_setcfg(modcontext * modctx, int samplerate, int bits, int stereo, int stereo_separation, int filter) +{ + if( modctx ) + { + modctx->playrate = samplerate; + + if( stereo ) + modctx->stereo = 1; + else + modctx->stereo = 0; + + if(stereo_separation < 4) + { + modctx->stereo_separation = stereo_separation; + } + + if( bits == 8 || bits == 16 ) + modctx->bits = bits; + else + modctx->bits = 16; + + if( filter ) + modctx->filter = 1; + else + modctx->filter = 0; + + return 1; + } + + return 0; +} + +// make certain that mod_data stays in memory while playing +static bool jar_mod_load( modcontext * modctx, void * mod_data, int mod_data_size ) +{ + muint i, max; + unsigned short t; + sample *sptr; + unsigned char * modmemory,* endmodmemory; + + modmemory = (unsigned char *)mod_data; + endmodmemory = modmemory + mod_data_size; + + + + if(modmemory) + { + if( modctx ) + { + memcopy(&(modctx->song.title),modmemory,1084); + + i = 0; + modctx->number_of_channels = 0; + while(modlist[i].numberofchannels) + { + if(memcompare(modctx->song.signature,modlist[i].signature,4)) + { + modctx->number_of_channels = modlist[i].numberofchannels; + } + + i++; + } + + if( !modctx->number_of_channels ) + { + // 15 Samples modules support + // Shift the whole datas to make it look likes a standard 4 channels mod. + memcopy(&(modctx->song.signature), "M.K.", 4); + memcopy(&(modctx->song.length), &(modctx->song.samples[15]), 130); + memclear(&(modctx->song.samples[15]), 0, 480); + modmemory += 600; + modctx->number_of_channels = 4; + } + else + { + modmemory += 1084; + } + + if( modmemory >= endmodmemory ) + return 0; // End passed ? - Probably a bad file ! + + // Patterns loading + for (i = max = 0; i < 128; i++) + { + while (max <= modctx->song.patterntable[i]) + { + modctx->patterndata[max] = (note*)modmemory; + modmemory += (256*modctx->number_of_channels); + max++; + + if( modmemory >= endmodmemory ) + return 0; // End passed ? - Probably a bad file ! + } + } + + for (i = 0; i < 31; i++) + modctx->sampledata[i]=0; + + // Samples loading + for (i = 0, sptr = modctx->song.samples; i <31; i++, sptr++) + { + t= (sptr->length &0xFF00)>>8 | (sptr->length &0xFF)<<8; + sptr->length = t*2; + + t= (sptr->reppnt &0xFF00)>>8 | (sptr->reppnt &0xFF)<<8; + sptr->reppnt = t*2; + + t= (sptr->replen &0xFF00)>>8 | (sptr->replen &0xFF)<<8; + sptr->replen = t*2; + + + if (sptr->length == 0) continue; + + modctx->sampledata[i] = (char*)modmemory; + modmemory += sptr->length; + + if (sptr->replen + sptr->reppnt > sptr->length) + sptr->replen = sptr->length - sptr->reppnt; + + if( modmemory > endmodmemory ) + return 0; // End passed ? - Probably a bad file ! + } + + // States init + + modctx->tablepos = 0; + modctx->patternpos = 0; + modctx->song.speed = 6; + modctx->bpm = 125; + modctx->samplenb = 0; + + modctx->patternticks = (((long)modctx->song.speed * modctx->playrate * 5)/ (2 * modctx->bpm)) + 1; + modctx->patternticksaim = ((long)modctx->song.speed * modctx->playrate * 5) / (2 * modctx->bpm); + + modctx->sampleticksconst = 3546894UL / modctx->playrate; //8448*428/playrate; + + for(i=0; i < modctx->number_of_channels; i++) + { + modctx->channels[i].volume = 0; + modctx->channels[i].period = 0; + } + + modctx->mod_loaded = 1; + + return 1; + } + } + + return 0; +} + +void jar_mod_fillbuffer( modcontext * modctx, short * outbuffer, unsigned long nbsample, jar_mod_tracker_buffer_state * trkbuf ) +{ + unsigned long i, j; + unsigned long k; + unsigned char c; + unsigned int state_remaining_steps; + int l,r; + int ll,lr; + int tl,tr; + short finalperiod; + note *nptr; + channel *cptr; + + if( modctx && outbuffer ) + { + if(modctx->mod_loaded) + { + state_remaining_steps = 0; + + if( trkbuf ) + { + trkbuf->cur_rd_index = 0; + + memcopy(trkbuf->name,modctx->song.title,sizeof(modctx->song.title)); + + for(i=0;i<31;i++) + { + memcopy(trkbuf->instruments[i].name,modctx->song.samples[i].name,sizeof(trkbuf->instruments[i].name)); + } + } + + ll = modctx->last_l_sample; + lr = modctx->last_r_sample; + + for (i = 0; i < nbsample; i++) + { + //--------------------------------------- + if( modctx->patternticks++ > modctx->patternticksaim ) + { + if( !modctx->patterndelay ) + { + nptr = modctx->patterndata[modctx->song.patterntable[modctx->tablepos]]; + nptr = nptr + modctx->patternpos; + cptr = modctx->channels; + + modctx->patternticks = 0; + modctx->patterntickse = 0; + + for(c=0;cnumber_of_channels;c++) + { + worknote((note*)(nptr+c), (channel*)(cptr+c),(char)(c+1),modctx); + } + + if( !modctx->jump_loop_effect ) + modctx->patternpos += modctx->number_of_channels; + else + modctx->jump_loop_effect = 0; + + if( modctx->patternpos == 64*modctx->number_of_channels ) + { + modctx->tablepos++; + modctx->patternpos = 0; + if(modctx->tablepos >= modctx->song.length) + { + modctx->tablepos = 0; + modctx->loopcount++; // count next loop + } + } + } + else + { + modctx->patterndelay--; + modctx->patternticks = 0; + modctx->patterntickse = 0; + } + + } + + if( modctx->patterntickse++ > (modctx->patternticksaim/modctx->song.speed) ) + { + nptr = modctx->patterndata[modctx->song.patterntable[modctx->tablepos]]; + nptr = nptr + modctx->patternpos; + cptr = modctx->channels; + + for(c=0;cnumber_of_channels;c++) + { + workeffect(nptr+c, cptr+c); + } + + modctx->patterntickse = 0; + } + + //--------------------------------------- + + if( trkbuf && !state_remaining_steps ) + { + if( trkbuf->nb_of_state < trkbuf->nb_max_of_state ) + { + memclear(&trkbuf->track_state_buf[trkbuf->nb_of_state], 0, sizeof(tracker_state)); + } + } + + l=0; + r=0; + + for(j =0, cptr = modctx->channels; j < modctx->number_of_channels ; j++, cptr++) + { + if( cptr->period != 0 ) + { + finalperiod = cptr->period - cptr->decalperiod - cptr->vibraperiod; + if( finalperiod ) + { + cptr->samppos += ( (modctx->sampleticksconst<<10) / finalperiod ); + } + + cptr->ticks++; + + if( cptr->replen<=2 ) + { + if( (cptr->samppos>>10) >= (cptr->length) ) + { + cptr->length = 0; + cptr->reppnt = 0; + + if( cptr->length ) + cptr->samppos = cptr->samppos % (((unsigned long)cptr->length)<<10); + else + cptr->samppos = 0; + } + } + else + { + if( (cptr->samppos>>10) >= (unsigned long)(cptr->replen+cptr->reppnt) ) + { + cptr->samppos = ((unsigned long)(cptr->reppnt)<<10) + (cptr->samppos % ((unsigned long)(cptr->replen+cptr->reppnt)<<10)); + } + } + + k = cptr->samppos >> 10; + + if( cptr->sampdata!=0 && ( ((j&3)==1) || ((j&3)==2) ) ) + { + r += ( cptr->sampdata[k] * cptr->volume ); + } + + if( cptr->sampdata!=0 && ( ((j&3)==0) || ((j&3)==3) ) ) + { + l += ( cptr->sampdata[k] * cptr->volume ); + } + + if( trkbuf && !state_remaining_steps ) + { + if( trkbuf->nb_of_state < trkbuf->nb_max_of_state ) + { + trkbuf->track_state_buf[trkbuf->nb_of_state].number_of_tracks = modctx->number_of_channels; + trkbuf->track_state_buf[trkbuf->nb_of_state].buf_index = i; + trkbuf->track_state_buf[trkbuf->nb_of_state].cur_pattern = modctx->song.patterntable[modctx->tablepos]; + trkbuf->track_state_buf[trkbuf->nb_of_state].cur_pattern_pos = modctx->patternpos / modctx->number_of_channels; + trkbuf->track_state_buf[trkbuf->nb_of_state].cur_pattern_table_pos = modctx->tablepos; + trkbuf->track_state_buf[trkbuf->nb_of_state].bpm = modctx->bpm; + trkbuf->track_state_buf[trkbuf->nb_of_state].speed = modctx->song.speed; + trkbuf->track_state_buf[trkbuf->nb_of_state].tracks[j].cur_effect = cptr->effect_code; + trkbuf->track_state_buf[trkbuf->nb_of_state].tracks[j].cur_parameffect = cptr->parameffect; + trkbuf->track_state_buf[trkbuf->nb_of_state].tracks[j].cur_period = finalperiod; + trkbuf->track_state_buf[trkbuf->nb_of_state].tracks[j].cur_volume = cptr->volume; + trkbuf->track_state_buf[trkbuf->nb_of_state].tracks[j].instrument_number = (unsigned char)cptr->sampnum; + } + } + } + } + + if( trkbuf && !state_remaining_steps ) + { + state_remaining_steps = trkbuf->sample_step; + + if(trkbuf->nb_of_state < trkbuf->nb_max_of_state) + trkbuf->nb_of_state++; + } + else + { + state_remaining_steps--; + } + + tl = (short)l; + tr = (short)r; + + if ( modctx->filter ) + { + // Filter + l = (l+ll)>>1; + r = (r+lr)>>1; + } + + if ( modctx->stereo_separation == 1 ) + { + // Left & Right Stereo panning + l = (l+(r>>1)); + r = (r+(l>>1)); + } + + // Level limitation + if( l > 32767 ) l = 32767; + if( l < -32768 ) l = -32768; + if( r > 32767 ) r = 32767; + if( r < -32768 ) r = -32768; + + // Store the final sample. + outbuffer[(i*2)] = l; + outbuffer[(i*2)+1] = r; + + ll = tl; + lr = tr; + + } + + modctx->last_l_sample = ll; + modctx->last_r_sample = lr; + + modctx->samplenb = modctx->samplenb+nbsample; + } + else + { + for (i = 0; i < nbsample; i++) + { + // Mod not loaded. Return blank buffer. + outbuffer[(i*2)] = 0; + outbuffer[(i*2)+1] = 0; + } + + if(trkbuf) + { + trkbuf->nb_of_state = 0; + trkbuf->cur_rd_index = 0; + trkbuf->name[0] = 0; + memclear(trkbuf->track_state_buf, 0, sizeof(tracker_state) * trkbuf->nb_max_of_state); + memclear(trkbuf->instruments, 0, sizeof(trkbuf->instruments)); + } + } + } +} + +void jar_mod_unload( modcontext * modctx) +{ + if(modctx) + { + if(modctx->modfile) + { + free(modctx->modfile); + modctx->modfile = 0; + } + memclear(&modctx->song, 0, sizeof(modctx->song)); + memclear(&modctx->sampledata, 0, sizeof(modctx->sampledata)); + memclear(&modctx->patterndata, 0, sizeof(modctx->patterndata)); + modctx->tablepos = 0; + modctx->patternpos = 0; + modctx->patterndelay = 0; + modctx->jump_loop_effect = 0; + modctx->bpm = 0; + modctx->patternticks = 0; + modctx->patterntickse = 0; + modctx->patternticksaim = 0; + modctx->sampleticksconst = 0; + modctx->loopcount = 0; + + modctx->samplenb = 0; + + memclear(modctx->channels, 0, sizeof(modctx->channels)); + + modctx->number_of_channels = 0; + + modctx->mod_loaded = 0; + + modctx->last_r_sample = 0; + modctx->last_l_sample = 0; + } +} + +mulong jar_mod_load_file(modcontext * modctx, char* filename) +{ + mulong fsize = 0; + if(modctx->modfile) + { + free(modctx->modfile); + modctx->modfile = 0; + } + + FILE *f = fopen(filename, "rb"); + if(f) + { + fseek(f,0,SEEK_END); + fsize = ftell(f); + fseek(f,0,SEEK_SET); + + if(fsize && fsize < 32*1024*1024) + { + modctx->modfile = malloc(fsize); + modctx->modfilesize = fsize; + memset(modctx->modfile, 0, fsize); + fread(modctx->modfile, fsize, 1, f); + fclose(f); + + if(!jar_mod_load(modctx, (void*)modctx->modfile, fsize)) fsize = 0; + } else fsize = 0; + } + return fsize; +} + +mulong jar_mod_current_samples(modcontext * modctx) +{ + if(modctx) + return modctx->samplenb; + + return 0; +} + +// Works, however it is very slow, this data should be cached to ensure it is run only once per file +mulong jar_mod_max_samples(modcontext * ctx) +{ + modcontext tmpctx; + jar_mod_init(&tmpctx); + if(!jar_mod_load(&tmpctx, (void*)ctx->modfile, ctx->modfilesize)) return 0; + + muint buff[2]; + mulong lastcount = tmpctx.loopcount; + + while(1){ + jar_mod_fillbuffer( &tmpctx, buff, 1, 0 ); + if(tmpctx.loopcount > lastcount) break; + } + return tmpctx.samplenb; +} + +// move seek_val to sample index, 0 -> jar_mod_max_samples is the range +void jar_mod_seek_start(modcontext * ctx) +{ + if(ctx) + { + char* tmpmodfile = ctx->modfile; + long size = ctx->modfilesize; + jar_mod_init(ctx); + jar_mod_load(ctx, tmpmodfile, size); + ctx->modfilesize = size; + ctx->modfile = tmpmodfile; + } +} + +#endif // end of JAR_MOD_IMPLEMENTATION +//------------------------------------------------------------------------------- + + +#endif //end of header file \ No newline at end of file diff --git a/src/raylib.h b/src/raylib.h index 456f427d..59266a0c 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -261,8 +261,9 @@ //---------------------------------------------------------------------------------- #ifndef __cplusplus // Boolean type - #ifndef true + #if !defined(_STDBOOL_H) typedef enum { false, true } bool; + #define _STDBOOL_H #endif #endif -- cgit v1.2.3 From af1eb5453acc2772afbc316375c403b31a742626 Mon Sep 17 00:00:00 2001 From: Joshua Reisenauer Date: Thu, 2 Jun 2016 02:02:23 -0700 Subject: I added audio errors The only thing I did not change was the _g for globals. Is there any other way we can mark globals? --- src/audio.c | 254 ++++++++++++++++++++++++++++++---------------------------- src/audio.h | 20 +++++ src/jar_mod.h | 58 +++++++------- src/raylib.h | 21 +++++ 4 files changed, 200 insertions(+), 153 deletions(-) (limited to 'src/raylib.h') diff --git a/src/audio.c b/src/audio.c index d9a527ee..452459ef 100644 --- a/src/audio.c +++ b/src/audio.c @@ -99,7 +99,7 @@ typedef struct MixChannel_t { typedef struct Music { stb_vorbis *stream; jar_xm_context_t *xmctx; // Stores jar_xm mixc, XM chiptune context - modcontext modctx; // Stores mod chiptune context + jar_mod_context_t modctx; // Stores mod chiptune context MixChannel_t *mixc; // mix channel unsigned int totalSamplesLeft; @@ -115,9 +115,9 @@ typedef enum { INFO = 0, ERROR, WARNING, DEBUG, OTHER } TraceLogType; //---------------------------------------------------------------------------------- // Global Variables Definition //---------------------------------------------------------------------------------- -static MixChannel_t* mixChannelsActive_g[MAX_MIX_CHANNELS]; // What mix channels are currently active +static MixChannel_t* mixChannels_g[MAX_MIX_CHANNELS]; // What mix channels are currently active static bool musicEnabled_g = false; -static Music currentMusic_g[MAX_MUSIC_STREAMS]; // Current music loaded, up to two can play at the same time +static Music musicChannels_g[MAX_MUSIC_STREAMS]; // Current music loaded, up to two can play at the same time //---------------------------------------------------------------------------------- // Module specific Functions Declaration @@ -179,7 +179,7 @@ void CloseAudioDevice(void) { for(int index=0; index= MAX_MIX_CHANNELS) return NULL; if(!IsAudioDeviceReady()) InitAudioDevice(); - if(!mixChannelsActive_g[mixChannel]){ + if(!mixChannels_g[mixChannel]){ MixChannel_t *mixc = (MixChannel_t*)malloc(sizeof(MixChannel_t)); mixc->sampleRate = sampleRate; mixc->channels = channels; mixc->mixChannel = mixChannel; mixc->floatingPoint = floatingPoint; - mixChannelsActive_g[mixChannel] = mixc; + mixChannels_g[mixChannel] = mixc; // setup openAL format if(channels == 1) @@ -287,7 +287,7 @@ static void CloseMixChannel(MixChannel_t* mixc) //delete source and buffers alDeleteSources(1, &mixc->alSource); alDeleteBuffers(MAX_STREAM_BUFFERS, mixc->alBuffer); - mixChannelsActive_g[mixc->mixChannel] = NULL; + mixChannels_g[mixc->mixChannel] = NULL; free(mixc); mixc = NULL; } @@ -298,7 +298,7 @@ static void CloseMixChannel(MixChannel_t* mixc) // @Returns number of samples that where processed. static int BufferMixChannel(MixChannel_t* mixc, void *data, int numberElements) { - if(!mixc || mixChannelsActive_g[mixc->mixChannel] != mixc) return 0; // when there is two channels there must be an even number of samples + if(!mixc || mixChannels_g[mixc->mixChannel] != mixc) return 0; // when there is two channels there must be an even number of samples if (!data || !numberElements) { // pauses audio until data is given @@ -387,20 +387,20 @@ RawAudioContext InitRawAudioContext(int sampleRate, int channels, bool floatingP int mixIndex; for(mixIndex = 0; mixIndex < MAX_MIX_CHANNELS; mixIndex++) // find empty mix channel slot { - if(mixChannelsActive_g[mixIndex] == NULL) break; - else if(mixIndex == MAX_MIX_CHANNELS - 1) return -1; // error + if(mixChannels_g[mixIndex] == NULL) break; + else if(mixIndex == MAX_MIX_CHANNELS - 1) return ERROR_OUT_OF_MIX_CHANNELS; // error } if(InitMixChannel(sampleRate, mixIndex, channels, floatingPoint)) return mixIndex; else - return -2; // error + return ERROR_RAW_CONTEXT_CREATION; // error } void CloseRawAudioContext(RawAudioContext ctx) { - if(mixChannelsActive_g[ctx]) - CloseMixChannel(mixChannelsActive_g[ctx]); + if(mixChannels_g[ctx]) + CloseMixChannel(mixChannels_g[ctx]); } // if 0 is returned, the buffers are still full and you need to keep trying with the same data until a + number is returned. @@ -411,7 +411,7 @@ int BufferRawAudioContext(RawAudioContext ctx, void *data, unsigned short number int numBuffered = 0; if(ctx >= 0) { - MixChannel_t* mixc = mixChannelsActive_g[ctx]; + MixChannel_t* mixc = mixChannels_g[ctx]; numBuffered = BufferMixChannel(mixc, data, numberElements); } return numBuffered; @@ -438,7 +438,10 @@ Sound LoadSound(char *fileName) if (strcmp(GetExtension(fileName),"wav") == 0) wave = LoadWAV(fileName); else if (strcmp(GetExtension(fileName),"ogg") == 0) wave = LoadOGG(fileName); - else TraceLog(WARNING, "[%s] Sound extension not recognized, it can't be loaded", fileName); + else{ + TraceLog(WARNING, "[%s] Sound extension not recognized, it can't be loaded", fileName); + sound.error = ERROR_EXTENSION_NOT_RECOGNIZED; //error + } if (wave.data != NULL) { @@ -565,6 +568,7 @@ Sound LoadSoundFromRES(const char *rresName, int resId) if (rresFile == NULL) { TraceLog(WARNING, "[%s] rRES raylib resource file could not be opened", rresName); + sound.error = ERROR_UNABLE_TO_OPEN_RRES_FILE; //error } else { @@ -579,6 +583,7 @@ Sound LoadSoundFromRES(const char *rresName, int resId) if ((id[0] != 'r') && (id[1] != 'R') && (id[2] != 'E') &&(id[3] != 'S')) { TraceLog(WARNING, "[%s] This is not a valid raylib resource file", rresName); + sound.error = ERROR_INVALID_RRES_FILE; } else { @@ -669,6 +674,7 @@ Sound LoadSoundFromRES(const char *rresName, int resId) else { TraceLog(WARNING, "[%s] Required resource do not seem to be a valid SOUND resource", rresName); + sound.error = ERROR_INVALID_RRES_RESOURCE; } } else @@ -774,134 +780,134 @@ int PlayMusicStream(int musicIndex, char *fileName) { int mixIndex; - if(currentMusic_g[musicIndex].stream || currentMusic_g[musicIndex].xmctx) return 1; // error + if(musicChannels_g[musicIndex].stream || musicChannels_g[musicIndex].xmctx) return ERROR_UNINITIALIZED_CHANNELS; // error for(mixIndex = 0; mixIndex < MAX_MIX_CHANNELS; mixIndex++) // find empty mix channel slot { - if(mixChannelsActive_g[mixIndex] == NULL) break; - else if(mixIndex == MAX_MIX_CHANNELS - 1) return 2; // error + if(mixChannels_g[mixIndex] == NULL) break; + else if(mixIndex == MAX_MIX_CHANNELS - 1) return ERROR_OUT_OF_MIX_CHANNELS; // error } if (strcmp(GetExtension(fileName),"ogg") == 0) { // Open audio stream - currentMusic_g[musicIndex].stream = stb_vorbis_open_filename(fileName, NULL, NULL); + musicChannels_g[musicIndex].stream = stb_vorbis_open_filename(fileName, NULL, NULL); - if (currentMusic_g[musicIndex].stream == NULL) + if (musicChannels_g[musicIndex].stream == NULL) { TraceLog(WARNING, "[%s] OGG audio file could not be opened", fileName); - return 3; // error + return ERROR_LOADING_OGG; // error } else { // Get file info - stb_vorbis_info info = stb_vorbis_get_info(currentMusic_g[musicIndex].stream); + stb_vorbis_info info = stb_vorbis_get_info(musicChannels_g[musicIndex].stream); TraceLog(INFO, "[%s] Ogg sample rate: %i", fileName, info.sample_rate); TraceLog(INFO, "[%s] Ogg channels: %i", fileName, info.channels); TraceLog(DEBUG, "[%s] Temp memory required: %i", fileName, info.temp_memory_required); - currentMusic_g[musicIndex].loop = true; // We loop by default + musicChannels_g[musicIndex].loop = true; // We loop by default musicEnabled_g = true; - currentMusic_g[musicIndex].totalSamplesLeft = (unsigned int)stb_vorbis_stream_length_in_samples(currentMusic_g[musicIndex].stream) * info.channels; - currentMusic_g[musicIndex].totalLengthSeconds = stb_vorbis_stream_length_in_seconds(currentMusic_g[musicIndex].stream); + musicChannels_g[musicIndex].totalSamplesLeft = (unsigned int)stb_vorbis_stream_length_in_samples(musicChannels_g[musicIndex].stream) * info.channels; + musicChannels_g[musicIndex].totalLengthSeconds = stb_vorbis_stream_length_in_seconds(musicChannels_g[musicIndex].stream); if (info.channels == 2){ - currentMusic_g[musicIndex].mixc = InitMixChannel(info.sample_rate, mixIndex, 2, false); - currentMusic_g[musicIndex].mixc->playing = true; + musicChannels_g[musicIndex].mixc = InitMixChannel(info.sample_rate, mixIndex, 2, false); + musicChannels_g[musicIndex].mixc->playing = true; } else{ - currentMusic_g[musicIndex].mixc = InitMixChannel(info.sample_rate, mixIndex, 1, false); - currentMusic_g[musicIndex].mixc->playing = true; + musicChannels_g[musicIndex].mixc = InitMixChannel(info.sample_rate, mixIndex, 1, false); + musicChannels_g[musicIndex].mixc->playing = true; } - if(!currentMusic_g[musicIndex].mixc) return 4; // error + if(!musicChannels_g[musicIndex].mixc) return ERROR_LOADING_OGG; // error } } else if (strcmp(GetExtension(fileName),"xm") == 0) { // only stereo is supported for xm - if(!jar_xm_create_context_from_file(¤tMusic_g[musicIndex].xmctx, 48000, fileName)) + if(!jar_xm_create_context_from_file(&musicChannels_g[musicIndex].xmctx, 48000, fileName)) { - currentMusic_g[musicIndex].chipTune = true; - currentMusic_g[musicIndex].loop = true; - jar_xm_set_max_loop_count(currentMusic_g[musicIndex].xmctx, 0); // infinite number of loops - currentMusic_g[musicIndex].totalSamplesLeft = (unsigned int)jar_xm_get_remaining_samples(currentMusic_g[musicIndex].xmctx); - currentMusic_g[musicIndex].totalLengthSeconds = ((float)currentMusic_g[musicIndex].totalSamplesLeft) / 48000.f; + musicChannels_g[musicIndex].chipTune = true; + musicChannels_g[musicIndex].loop = true; + jar_xm_set_max_loop_count(musicChannels_g[musicIndex].xmctx, 0); // infinite number of loops + musicChannels_g[musicIndex].totalSamplesLeft = (unsigned int)jar_xm_get_remaining_samples(musicChannels_g[musicIndex].xmctx); + musicChannels_g[musicIndex].totalLengthSeconds = ((float)musicChannels_g[musicIndex].totalSamplesLeft) / 48000.f; musicEnabled_g = true; - TraceLog(INFO, "[%s] XM number of samples: %i", fileName, currentMusic_g[musicIndex].totalSamplesLeft); - TraceLog(INFO, "[%s] XM track length: %11.6f sec", fileName, currentMusic_g[musicIndex].totalLengthSeconds); + TraceLog(INFO, "[%s] XM number of samples: %i", fileName, musicChannels_g[musicIndex].totalSamplesLeft); + TraceLog(INFO, "[%s] XM track length: %11.6f sec", fileName, musicChannels_g[musicIndex].totalLengthSeconds); - currentMusic_g[musicIndex].mixc = InitMixChannel(48000, mixIndex, 2, true); - if(!currentMusic_g[musicIndex].mixc) return 5; // error - currentMusic_g[musicIndex].mixc->playing = true; + musicChannels_g[musicIndex].mixc = InitMixChannel(48000, mixIndex, 2, true); + if(!musicChannels_g[musicIndex].mixc) return ERROR_XM_CONTEXT_CREATION; // error + musicChannels_g[musicIndex].mixc->playing = true; } else { TraceLog(WARNING, "[%s] XM file could not be opened", fileName); - return 6; // error + return ERROR_LOADING_XM; // error } } else if (strcmp(GetExtension(fileName),"mod") == 0) { - jar_mod_init(¤tMusic_g[musicIndex].modctx); - if(jar_mod_load_file(¤tMusic_g[musicIndex].modctx, fileName)) + jar_mod_init(&musicChannels_g[musicIndex].modctx); + if(jar_mod_load_file(&musicChannels_g[musicIndex].modctx, fileName)) { - currentMusic_g[musicIndex].chipTune = true; - currentMusic_g[musicIndex].loop = true; - currentMusic_g[musicIndex].totalSamplesLeft = (unsigned int)jar_mod_max_samples(¤tMusic_g[musicIndex].modctx); - currentMusic_g[musicIndex].totalLengthSeconds = ((float)currentMusic_g[musicIndex].totalSamplesLeft) / 48000.f; + musicChannels_g[musicIndex].chipTune = true; + musicChannels_g[musicIndex].loop = true; + musicChannels_g[musicIndex].totalSamplesLeft = (unsigned int)jar_mod_max_samples(&musicChannels_g[musicIndex].modctx); + musicChannels_g[musicIndex].totalLengthSeconds = ((float)musicChannels_g[musicIndex].totalSamplesLeft) / 48000.f; musicEnabled_g = true; - TraceLog(INFO, "[%s] MOD number of samples: %i", fileName, currentMusic_g[musicIndex].totalSamplesLeft); - TraceLog(INFO, "[%s] MOD track length: %11.6f sec", fileName, currentMusic_g[musicIndex].totalLengthSeconds); + TraceLog(INFO, "[%s] MOD number of samples: %i", fileName, musicChannels_g[musicIndex].totalSamplesLeft); + TraceLog(INFO, "[%s] MOD track length: %11.6f sec", fileName, musicChannels_g[musicIndex].totalLengthSeconds); - currentMusic_g[musicIndex].mixc = InitMixChannel(48000, mixIndex, 2, false); - if(!currentMusic_g[musicIndex].mixc) return 7; // error - currentMusic_g[musicIndex].mixc->playing = true; + musicChannels_g[musicIndex].mixc = InitMixChannel(48000, mixIndex, 2, false); + if(!musicChannels_g[musicIndex].mixc) return ERROR_MOD_CONTEXT_CREATION; // error + musicChannels_g[musicIndex].mixc->playing = true; } else { TraceLog(WARNING, "[%s] MOD file could not be opened", fileName); - return 8; // error + return ERROR_LOADING_MOD; // error } } else { TraceLog(WARNING, "[%s] Music extension not recognized, it can't be loaded", fileName); - return 9; // error + return ERROR_EXTENSION_NOT_RECOGNIZED; // error } return 0; // normal return } -// Stop music playing for individual music index of currentMusic_g array (close stream) +// Stop music playing for individual music index of musicChannels_g array (close stream) void StopMusicStream(int index) { - if (index < MAX_MUSIC_STREAMS && currentMusic_g[index].mixc) + if (index < MAX_MUSIC_STREAMS && musicChannels_g[index].mixc) { - CloseMixChannel(currentMusic_g[index].mixc); + CloseMixChannel(musicChannels_g[index].mixc); - if (currentMusic_g[index].chipTune && currentMusic_g[index].xmctx) + if (musicChannels_g[index].chipTune && musicChannels_g[index].xmctx) { - jar_xm_free_context(currentMusic_g[index].xmctx); - currentMusic_g[index].xmctx = 0; + jar_xm_free_context(musicChannels_g[index].xmctx); + musicChannels_g[index].xmctx = 0; } - else if(currentMusic_g[index].chipTune && currentMusic_g[index].modctx.mod_loaded) + else if(musicChannels_g[index].chipTune && musicChannels_g[index].modctx.mod_loaded) { - jar_mod_unload(¤tMusic_g[index].modctx); + jar_mod_unload(&musicChannels_g[index].modctx); } else { - stb_vorbis_close(currentMusic_g[index].stream); + stb_vorbis_close(musicChannels_g[index].stream); } if(!getMusicStreamCount()) musicEnabled_g = false; - if(currentMusic_g[index].stream || currentMusic_g[index].xmctx) + if(musicChannels_g[index].stream || musicChannels_g[index].xmctx) { - currentMusic_g[index].stream = NULL; - currentMusic_g[index].xmctx = NULL; + musicChannels_g[index].stream = NULL; + musicChannels_g[index].xmctx = NULL; } } } @@ -911,7 +917,7 @@ int getMusicStreamCount(void) { int musicCount = 0; for(int musicIndex = 0; musicIndex < MAX_MUSIC_STREAMS; musicIndex++) // find empty music slot - if(currentMusic_g[musicIndex].stream != NULL || currentMusic_g[musicIndex].chipTune) musicCount++; + if(musicChannels_g[musicIndex].stream != NULL || musicChannels_g[musicIndex].chipTune) musicCount++; return musicCount; } @@ -920,11 +926,11 @@ int getMusicStreamCount(void) void PauseMusicStream(int index) { // Pause music stream if music available! - if (index < MAX_MUSIC_STREAMS && currentMusic_g[index].mixc && musicEnabled_g) + if (index < MAX_MUSIC_STREAMS && musicChannels_g[index].mixc && musicEnabled_g) { TraceLog(INFO, "Pausing music stream"); - alSourcePause(currentMusic_g[index].mixc->alSource); - currentMusic_g[index].mixc->playing = false; + alSourcePause(musicChannels_g[index].mixc->alSource); + musicChannels_g[index].mixc->playing = false; } } @@ -933,13 +939,13 @@ void ResumeMusicStream(int index) { // Resume music playing... if music available! ALenum state; - if(index < MAX_MUSIC_STREAMS && currentMusic_g[index].mixc){ - alGetSourcei(currentMusic_g[index].mixc->alSource, AL_SOURCE_STATE, &state); + if(index < MAX_MUSIC_STREAMS && musicChannels_g[index].mixc){ + alGetSourcei(musicChannels_g[index].mixc->alSource, AL_SOURCE_STATE, &state); if (state == AL_PAUSED) { TraceLog(INFO, "Resuming music stream"); - alSourcePlay(currentMusic_g[index].mixc->alSource); - currentMusic_g[index].mixc->playing = true; + alSourcePlay(musicChannels_g[index].mixc->alSource); + musicChannels_g[index].mixc->playing = true; } } } @@ -950,8 +956,8 @@ bool IsMusicPlaying(int index) bool playing = false; ALint state; - if(index < MAX_MUSIC_STREAMS && currentMusic_g[index].mixc){ - alGetSourcei(currentMusic_g[index].mixc->alSource, AL_SOURCE_STATE, &state); + if(index < MAX_MUSIC_STREAMS && musicChannels_g[index].mixc){ + alGetSourcei(musicChannels_g[index].mixc->alSource, AL_SOURCE_STATE, &state); if (state == AL_PLAYING) playing = true; } @@ -961,15 +967,15 @@ bool IsMusicPlaying(int index) // Set volume for music void SetMusicVolume(int index, float volume) { - if(index < MAX_MUSIC_STREAMS && currentMusic_g[index].mixc){ - alSourcef(currentMusic_g[index].mixc->alSource, AL_GAIN, volume); + if(index < MAX_MUSIC_STREAMS && musicChannels_g[index].mixc){ + alSourcef(musicChannels_g[index].mixc->alSource, AL_GAIN, volume); } } void SetMusicPitch(int index, float pitch) { - if(index < MAX_MUSIC_STREAMS && currentMusic_g[index].mixc){ - alSourcef(currentMusic_g[index].mixc->alSource, AL_PITCH, pitch); + if(index < MAX_MUSIC_STREAMS && musicChannels_g[index].mixc){ + alSourcef(musicChannels_g[index].mixc->alSource, AL_PITCH, pitch); } } @@ -977,13 +983,13 @@ void SetMusicPitch(int index, float pitch) float GetMusicTimeLength(int index) { float totalSeconds; - if (currentMusic_g[index].chipTune) + if (musicChannels_g[index].chipTune) { - totalSeconds = (float)currentMusic_g[index].totalLengthSeconds; + totalSeconds = (float)musicChannels_g[index].totalLengthSeconds; } else { - totalSeconds = stb_vorbis_stream_length_in_seconds(currentMusic_g[index].stream); + totalSeconds = stb_vorbis_stream_length_in_seconds(musicChannels_g[index].stream); } return totalSeconds; @@ -993,24 +999,24 @@ float GetMusicTimeLength(int index) float GetMusicTimePlayed(int index) { float secondsPlayed = 0.0f; - if(index < MAX_MUSIC_STREAMS && currentMusic_g[index].mixc) + if(index < MAX_MUSIC_STREAMS && musicChannels_g[index].mixc) { - if (currentMusic_g[index].chipTune && currentMusic_g[index].xmctx) + if (musicChannels_g[index].chipTune && musicChannels_g[index].xmctx) { uint64_t samples; - jar_xm_get_position(currentMusic_g[index].xmctx, NULL, NULL, NULL, &samples); - secondsPlayed = (float)samples / (48000.f * currentMusic_g[index].mixc->channels); // Not sure if this is the correct value + jar_xm_get_position(musicChannels_g[index].xmctx, NULL, NULL, NULL, &samples); + secondsPlayed = (float)samples / (48000.f * musicChannels_g[index].mixc->channels); // Not sure if this is the correct value } - else if(currentMusic_g[index].chipTune && currentMusic_g[index].modctx.mod_loaded) + else if(musicChannels_g[index].chipTune && musicChannels_g[index].modctx.mod_loaded) { - long numsamp = jar_mod_current_samples(¤tMusic_g[index].modctx); + long numsamp = jar_mod_current_samples(&musicChannels_g[index].modctx); secondsPlayed = (float)numsamp / (48000.f); } else { - int totalSamples = stb_vorbis_stream_length_in_samples(currentMusic_g[index].stream) * currentMusic_g[index].mixc->channels; - int samplesPlayed = totalSamples - currentMusic_g[index].totalSamplesLeft; - secondsPlayed = (float)samplesPlayed / (currentMusic_g[index].mixc->sampleRate * currentMusic_g[index].mixc->channels); + int totalSamples = stb_vorbis_stream_length_in_samples(musicChannels_g[index].stream) * musicChannels_g[index].mixc->channels; + int samplesPlayed = totalSamples - musicChannels_g[index].totalSamplesLeft; + secondsPlayed = (float)samplesPlayed / (musicChannels_g[index].mixc->sampleRate * musicChannels_g[index].mixc->channels); } } @@ -1030,30 +1036,30 @@ static bool BufferMusicStream(int index, int numBuffers) int size = 0; // Total size of data steamed in L+R samples for xm floats, individual L or R for ogg shorts bool active = true; // We can get more data from stream (not finished) - if (currentMusic_g[index].chipTune) // There is no end of stream for xmfiles, once the end is reached zeros are generated for non looped chiptunes. + if (musicChannels_g[index].chipTune) // There is no end of stream for xmfiles, once the end is reached zeros are generated for non looped chiptunes. { for(int x=0; x= MUSIC_BUFFER_SIZE_SHORT) + if(musicChannels_g[index].modctx.mod_loaded){ + if(musicChannels_g[index].totalSamplesLeft >= MUSIC_BUFFER_SIZE_SHORT) size = MUSIC_BUFFER_SIZE_SHORT / 2; else - size = currentMusic_g[index].totalSamplesLeft / 2; - jar_mod_fillbuffer(¤tMusic_g[index].modctx, pcm, size, 0 ); - BufferMixChannel(currentMusic_g[index].mixc, pcm, size * 2); + size = musicChannels_g[index].totalSamplesLeft / 2; + jar_mod_fillbuffer(&musicChannels_g[index].modctx, pcm, size, 0 ); + BufferMixChannel(musicChannels_g[index].mixc, pcm, size * 2); } - else if(currentMusic_g[index].xmctx){ - if(currentMusic_g[index].totalSamplesLeft >= MUSIC_BUFFER_SIZE_FLOAT) + else if(musicChannels_g[index].xmctx){ + if(musicChannels_g[index].totalSamplesLeft >= MUSIC_BUFFER_SIZE_FLOAT) size = MUSIC_BUFFER_SIZE_FLOAT / 2; else - size = currentMusic_g[index].totalSamplesLeft / 2; - jar_xm_generate_samples(currentMusic_g[index].xmctx, pcmf, size); // reads 2*readlen shorts and moves them to buffer+size memory location - BufferMixChannel(currentMusic_g[index].mixc, pcmf, size * 2); + size = musicChannels_g[index].totalSamplesLeft / 2; + jar_xm_generate_samples(musicChannels_g[index].xmctx, pcmf, size); // reads 2*readlen shorts and moves them to buffer+size memory location + BufferMixChannel(musicChannels_g[index].mixc, pcmf, size * 2); } - currentMusic_g[index].totalSamplesLeft -= size; - if(currentMusic_g[index].totalSamplesLeft <= 0) + musicChannels_g[index].totalSamplesLeft -= size; + if(musicChannels_g[index].totalSamplesLeft <= 0) { active = false; break; @@ -1062,17 +1068,17 @@ static bool BufferMusicStream(int index, int numBuffers) } else { - if(currentMusic_g[index].totalSamplesLeft >= MUSIC_BUFFER_SIZE_SHORT) + if(musicChannels_g[index].totalSamplesLeft >= MUSIC_BUFFER_SIZE_SHORT) size = MUSIC_BUFFER_SIZE_SHORT; else - size = currentMusic_g[index].totalSamplesLeft; + size = musicChannels_g[index].totalSamplesLeft; for(int x=0; xchannels, pcm, size); - BufferMixChannel(currentMusic_g[index].mixc, pcm, streamedBytes * currentMusic_g[index].mixc->channels); - currentMusic_g[index].totalSamplesLeft -= streamedBytes * currentMusic_g[index].mixc->channels; - if(currentMusic_g[index].totalSamplesLeft <= 0) + int streamedBytes = stb_vorbis_get_samples_short_interleaved(musicChannels_g[index].stream, musicChannels_g[index].mixc->channels, pcm, size); + BufferMixChannel(musicChannels_g[index].mixc, pcm, streamedBytes * musicChannels_g[index].mixc->channels); + musicChannels_g[index].totalSamplesLeft -= streamedBytes * musicChannels_g[index].mixc->channels; + if(musicChannels_g[index].totalSamplesLeft <= 0) { active = false; break; @@ -1089,11 +1095,11 @@ static void EmptyMusicStream(int index) ALuint buffer = 0; int queued = 0; - alGetSourcei(currentMusic_g[index].mixc->alSource, AL_BUFFERS_QUEUED, &queued); + alGetSourcei(musicChannels_g[index].mixc->alSource, AL_BUFFERS_QUEUED, &queued); while (queued > 0) { - alSourceUnqueueBuffers(currentMusic_g[index].mixc->alSource, 1, &buffer); + alSourceUnqueueBuffers(musicChannels_g[index].mixc->alSource, 1, &buffer); queued--; } @@ -1103,7 +1109,7 @@ static void EmptyMusicStream(int index) static int IsMusicStreamReadyForBuffering(int index) { ALint processed = 0; - alGetSourcei(currentMusic_g[index].mixc->alSource, AL_BUFFERS_PROCESSED, &processed); + alGetSourcei(musicChannels_g[index].mixc->alSource, AL_BUFFERS_PROCESSED, &processed); return processed; } @@ -1114,21 +1120,21 @@ void UpdateMusicStream(int index) bool active = true; int numBuffers = IsMusicStreamReadyForBuffering(index); - if (currentMusic_g[index].mixc->playing && index < MAX_MUSIC_STREAMS && musicEnabled_g && currentMusic_g[index].mixc && numBuffers) + if (musicChannels_g[index].mixc->playing && index < MAX_MUSIC_STREAMS && musicEnabled_g && musicChannels_g[index].mixc && numBuffers) { active = BufferMusicStream(index, numBuffers); - if (!active && currentMusic_g[index].loop) + if (!active && musicChannels_g[index].loop) { - if (currentMusic_g[index].chipTune) + if (musicChannels_g[index].chipTune) { - if(currentMusic_g[index].modctx.mod_loaded) jar_mod_seek_start(¤tMusic_g[index].modctx); - currentMusic_g[index].totalSamplesLeft = currentMusic_g[index].totalLengthSeconds * 48000; + if(musicChannels_g[index].modctx.mod_loaded) jar_mod_seek_start(&musicChannels_g[index].modctx); + musicChannels_g[index].totalSamplesLeft = musicChannels_g[index].totalLengthSeconds * 48000; } else { - stb_vorbis_seek_start(currentMusic_g[index].stream); - currentMusic_g[index].totalSamplesLeft = stb_vorbis_stream_length_in_samples(currentMusic_g[index].stream) * currentMusic_g[index].mixc->channels; + stb_vorbis_seek_start(musicChannels_g[index].stream); + musicChannels_g[index].totalSamplesLeft = stb_vorbis_stream_length_in_samples(musicChannels_g[index].stream) * musicChannels_g[index].mixc->channels; } active = true; } @@ -1136,9 +1142,9 @@ void UpdateMusicStream(int index) if (alGetError() != AL_NO_ERROR) TraceLog(WARNING, "Error buffering data..."); - alGetSourcei(currentMusic_g[index].mixc->alSource, AL_SOURCE_STATE, &state); + alGetSourcei(musicChannels_g[index].mixc->alSource, AL_SOURCE_STATE, &state); - if (state != AL_PLAYING && active) alSourcePlay(currentMusic_g[index].mixc->alSource); + if (state != AL_PLAYING && active) alSourcePlay(musicChannels_g[index].mixc->alSource); if (!active) StopMusicStream(index); diff --git a/src/audio.h b/src/audio.h index ca56032e..4baa30df 100644 --- a/src/audio.h +++ b/src/audio.h @@ -47,10 +47,29 @@ #endif #endif +typedef enum { + ERROR_RAW_CONTEXT_CREATION = -20, + ERROR_XM_CONTEXT_CREATION, + ERROR_MOD_CONTEXT_CREATION, + ERROR_MIX_CHANNEL_CREATION, + ERROR_MUSIC_CHANNEL_CREATION, + ERROR_LOADING_XM, + ERROR_LOADING_MOD, + ERROR_LOADING_WAV, + ERROR_LOADING_OGG, + ERROR_OUT_OF_MIX_CHANNELS, + ERROR_EXTENSION_NOT_RECOGNIZED, + ERROR_UNABLE_TO_OPEN_RRES_FILE, + ERROR_INVALID_RRES_FILE, + ERROR_INVALID_RRES_RESOURCE, + ERROR_UNINITIALIZED_CHANNELS +} AudioError; + // Sound source type typedef struct Sound { unsigned int source; unsigned int buffer; + AudioError error; // if there was any error during the creation or use of this Sound } Sound; // Wave type, defines audio wave data @@ -64,6 +83,7 @@ typedef struct Wave { typedef int RawAudioContext; + #ifdef __cplusplus extern "C" { // Prevents name mangling of functions #endif diff --git a/src/jar_mod.h b/src/jar_mod.h index 2066ef07..2ddc61d1 100644 --- a/src/jar_mod.h +++ b/src/jar_mod.h @@ -15,7 +15,7 @@ // Other source files should just include jar_mod.h // // SAMPLE CODE: -// modcontext modctx; +// jar_mod_context_t modctx; // short samplebuff[4096]; // bool bufferFull = false; // int intro_load(void) @@ -54,17 +54,17 @@ /////////////////////////////////////////////////////////////////////////////////// // HxCMOD Core API: // ------------------------------------------- -// int jar_mod_init(modcontext * modctx) +// int jar_mod_init(jar_mod_context_t * modctx) // -// - Initialize the modcontext buffer. Must be called before doing anything else. +// - Initialize the jar_mod_context_t buffer. Must be called before doing anything else. // Return 1 if success. 0 in case of error. // ------------------------------------------- -// mulong jar_mod_load_file(modcontext * modctx, char* filename) +// mulong jar_mod_load_file(jar_mod_context_t * modctx, char* filename) // // - "Load" a MOD from file, context must already be initialized. // Return size of file in bytes. // ------------------------------------------- -// void jar_mod_fillbuffer( modcontext * modctx, unsigned short * outbuffer, unsigned long nbsample, jar_mod_tracker_buffer_state * trkbuf ) +// void jar_mod_fillbuffer( jar_mod_context_t * modctx, unsigned short * outbuffer, unsigned long nbsample, jar_mod_tracker_buffer_state * trkbuf ) // // - Generate and return the next samples chunk to outbuffer. // nbsample specify the number of stereo 16bits samples you want. @@ -72,7 +72,7 @@ // The output buffer size in bytes must be equal to ( nbsample * 2 * channels ). // The optional trkbuf parameter can be used to get detailed status of the player. Put NULL/0 is unused. // ------------------------------------------- -// void jar_mod_unload( modcontext * modctx ) +// void jar_mod_unload( jar_mod_context_t * modctx ) // - "Unload" / clear the player status. // ------------------------------------------- /////////////////////////////////////////////////////////////////////////////////// @@ -198,7 +198,7 @@ typedef struct { muchar *modfile; // the raw mod file mulong modfilesize; muint loopcount; -} modcontext; +} jar_mod_context_t; // // Player states structures @@ -243,14 +243,14 @@ typedef struct jar_mod_tracker_buffer_state_ -bool jar_mod_init(modcontext * modctx); -bool jar_mod_setcfg(modcontext * modctx, int samplerate, int bits, int stereo, int stereo_separation, int filter); -void jar_mod_fillbuffer(modcontext * modctx, short * outbuffer, unsigned long nbsample, jar_mod_tracker_buffer_state * trkbuf); -void jar_mod_unload(modcontext * modctx); -mulong jar_mod_load_file(modcontext * modctx, char* filename); -mulong jar_mod_current_samples(modcontext * modctx); -mulong jar_mod_max_samples(modcontext * modctx); -void jar_mod_seek_start(modcontext * ctx); +bool jar_mod_init(jar_mod_context_t * modctx); +bool jar_mod_setcfg(jar_mod_context_t * modctx, int samplerate, int bits, int stereo, int stereo_separation, int filter); +void jar_mod_fillbuffer(jar_mod_context_t * modctx, short * outbuffer, unsigned long nbsample, jar_mod_tracker_buffer_state * trkbuf); +void jar_mod_unload(jar_mod_context_t * modctx); +mulong jar_mod_load_file(jar_mod_context_t * modctx, char* filename); +mulong jar_mod_current_samples(jar_mod_context_t * modctx); +mulong jar_mod_max_samples(jar_mod_context_t * modctx); +void jar_mod_seek_start(jar_mod_context_t * ctx); #ifdef __cplusplus } @@ -398,7 +398,7 @@ static int memcompare( unsigned char * buf1, unsigned char * buf2, unsigned int return 1; } -static int getnote( modcontext * mod, unsigned short period, int finetune ) +static int getnote( jar_mod_context_t * mod, unsigned short period, int finetune ) { int i; @@ -413,7 +413,7 @@ static int getnote( modcontext * mod, unsigned short period, int finetune ) return MAXNOTES; } -static void worknote( note * nptr, channel * cptr, char t, modcontext * mod ) +static void worknote( note * nptr, channel * cptr, char t, jar_mod_context_t * mod ) { muint sample, period, effect, operiod; muint curnote, arpnote; @@ -1051,13 +1051,13 @@ static void workeffect( note * nptr, channel * cptr ) } /////////////////////////////////////////////////////////////////////////////////// -bool jar_mod_init(modcontext * modctx) +bool jar_mod_init(jar_mod_context_t * modctx) { muint i,j; if( modctx ) { - memclear(modctx, 0, sizeof(modcontext)); + memclear(modctx, 0, sizeof(jar_mod_context_t)); modctx->playrate = DEFAULT_SAMPLE_RATE; modctx->stereo = 1; modctx->stereo_separation = 1; @@ -1079,7 +1079,7 @@ bool jar_mod_init(modcontext * modctx) return 0; } -bool jar_mod_setcfg(modcontext * modctx, int samplerate, int bits, int stereo, int stereo_separation, int filter) +bool jar_mod_setcfg(jar_mod_context_t * modctx, int samplerate, int bits, int stereo, int stereo_separation, int filter) { if( modctx ) { @@ -1112,7 +1112,7 @@ bool jar_mod_setcfg(modcontext * modctx, int samplerate, int bits, int stereo, i } // make certain that mod_data stays in memory while playing -static bool jar_mod_load( modcontext * modctx, void * mod_data, int mod_data_size ) +static bool jar_mod_load( jar_mod_context_t * modctx, void * mod_data, int mod_data_size ) { muint i, max; unsigned short t; @@ -1230,7 +1230,7 @@ static bool jar_mod_load( modcontext * modctx, void * mod_data, int mod_data_siz return 0; } -void jar_mod_fillbuffer( modcontext * modctx, short * outbuffer, unsigned long nbsample, jar_mod_tracker_buffer_state * trkbuf ) +void jar_mod_fillbuffer( jar_mod_context_t * modctx, short * outbuffer, unsigned long nbsample, jar_mod_tracker_buffer_state * trkbuf ) { unsigned long i, j; unsigned long k; @@ -1472,7 +1472,7 @@ void jar_mod_fillbuffer( modcontext * modctx, short * outbuffer, unsigned long n } //resets internals for mod context -static void jar_mod_reset( modcontext * modctx) +static void jar_mod_reset( jar_mod_context_t * modctx) { if(modctx) { @@ -1500,7 +1500,7 @@ static void jar_mod_reset( modcontext * modctx) } } -void jar_mod_unload( modcontext * modctx) +void jar_mod_unload( jar_mod_context_t * modctx) { if(modctx) { @@ -1515,7 +1515,7 @@ void jar_mod_unload( modcontext * modctx) -mulong jar_mod_load_file(modcontext * modctx, char* filename) +mulong jar_mod_load_file(jar_mod_context_t * modctx, char* filename) { mulong fsize = 0; if(modctx->modfile) @@ -1545,7 +1545,7 @@ mulong jar_mod_load_file(modcontext * modctx, char* filename) return fsize; } -mulong jar_mod_current_samples(modcontext * modctx) +mulong jar_mod_current_samples(jar_mod_context_t * modctx) { if(modctx) return modctx->samplenb; @@ -1554,9 +1554,9 @@ mulong jar_mod_current_samples(modcontext * modctx) } // Works, however it is very slow, this data should be cached to ensure it is run only once per file -mulong jar_mod_max_samples(modcontext * ctx) +mulong jar_mod_max_samples(jar_mod_context_t * ctx) { - modcontext tmpctx; + jar_mod_context_t tmpctx; jar_mod_init(&tmpctx); if(!jar_mod_load(&tmpctx, (void*)ctx->modfile, ctx->modfilesize)) return 0; @@ -1571,7 +1571,7 @@ mulong jar_mod_max_samples(modcontext * ctx) } // move seek_val to sample index, 0 -> jar_mod_max_samples is the range -void jar_mod_seek_start(modcontext * ctx) +void jar_mod_seek_start(jar_mod_context_t * ctx) { if(ctx) { diff --git a/src/raylib.h b/src/raylib.h index 47dd5d5b..a280b09e 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -452,10 +452,29 @@ typedef struct Ray { Vector3 direction; } Ray; +typedef enum { + ERROR_RAW_CONTEXT_CREATION = -20, + ERROR_XM_CONTEXT_CREATION, + ERROR_MOD_CONTEXT_CREATION, + ERROR_MIX_CHANNEL_CREATION, + ERROR_MUSIC_CHANNEL_CREATION, + ERROR_LOADING_XM, + ERROR_LOADING_MOD, + ERROR_LOADING_WAV, + ERROR_LOADING_OGG, + ERROR_OUT_OF_MIX_CHANNELS, + ERROR_EXTENSION_NOT_RECOGNIZED, + ERROR_UNABLE_TO_OPEN_RRES_FILE, + ERROR_INVALID_RRES_FILE, + ERROR_INVALID_RRES_RESOURCE, + ERROR_UNINITIALIZED_CHANNELS +} AudioError; + // Sound source type typedef struct Sound { unsigned int source; unsigned int buffer; + AudioError error; // if there was any error during the creation or use of this Sound } Sound; // Wave type, defines audio wave data @@ -469,6 +488,8 @@ typedef struct Wave { typedef int RawAudioContext; + + // Texture formats // NOTE: Support depends on OpenGL version and platform typedef enum { -- cgit v1.2.3 From cf2975d062a991d69fde60c3cdc043a8a39a09dc Mon Sep 17 00:00:00 2001 From: Joshua Reisenauer Date: Thu, 2 Jun 2016 02:31:25 -0700 Subject: convenient way to combine errors --- src/audio.h | 30 +++++++++++++++--------------- src/raylib.h | 32 ++++++++++++++++---------------- 2 files changed, 31 insertions(+), 31 deletions(-) (limited to 'src/raylib.h') diff --git a/src/audio.h b/src/audio.h index 4baa30df..a7475566 100644 --- a/src/audio.h +++ b/src/audio.h @@ -48,21 +48,21 @@ #endif typedef enum { - ERROR_RAW_CONTEXT_CREATION = -20, - ERROR_XM_CONTEXT_CREATION, - ERROR_MOD_CONTEXT_CREATION, - ERROR_MIX_CHANNEL_CREATION, - ERROR_MUSIC_CHANNEL_CREATION, - ERROR_LOADING_XM, - ERROR_LOADING_MOD, - ERROR_LOADING_WAV, - ERROR_LOADING_OGG, - ERROR_OUT_OF_MIX_CHANNELS, - ERROR_EXTENSION_NOT_RECOGNIZED, - ERROR_UNABLE_TO_OPEN_RRES_FILE, - ERROR_INVALID_RRES_FILE, - ERROR_INVALID_RRES_RESOURCE, - ERROR_UNINITIALIZED_CHANNELS + ERROR_RAW_CONTEXT_CREATION = 1, + ERROR_XM_CONTEXT_CREATION = 2, + ERROR_MOD_CONTEXT_CREATION = 4, + ERROR_MIX_CHANNEL_CREATION = 8, + ERROR_MUSIC_CHANNEL_CREATION = 16, + ERROR_LOADING_XM = 32, + ERROR_LOADING_MOD = 64, + ERROR_LOADING_WAV = 128, + ERROR_LOADING_OGG = 256, + ERROR_OUT_OF_MIX_CHANNELS = 512, + ERROR_EXTENSION_NOT_RECOGNIZED = 1024, + ERROR_UNABLE_TO_OPEN_RRES_FILE = 2048, + ERROR_INVALID_RRES_FILE = 4096, + ERROR_INVALID_RRES_RESOURCE = 8192, + ERROR_UNINITIALIZED_CHANNELS = 16384 } AudioError; // Sound source type diff --git a/src/raylib.h b/src/raylib.h index a280b09e..21892d68 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -452,22 +452,22 @@ typedef struct Ray { Vector3 direction; } Ray; -typedef enum { - ERROR_RAW_CONTEXT_CREATION = -20, - ERROR_XM_CONTEXT_CREATION, - ERROR_MOD_CONTEXT_CREATION, - ERROR_MIX_CHANNEL_CREATION, - ERROR_MUSIC_CHANNEL_CREATION, - ERROR_LOADING_XM, - ERROR_LOADING_MOD, - ERROR_LOADING_WAV, - ERROR_LOADING_OGG, - ERROR_OUT_OF_MIX_CHANNELS, - ERROR_EXTENSION_NOT_RECOGNIZED, - ERROR_UNABLE_TO_OPEN_RRES_FILE, - ERROR_INVALID_RRES_FILE, - ERROR_INVALID_RRES_RESOURCE, - ERROR_UNINITIALIZED_CHANNELS +typedef enum { // allows errors to be & together + ERROR_RAW_CONTEXT_CREATION = 1, + ERROR_XM_CONTEXT_CREATION = 2, + ERROR_MOD_CONTEXT_CREATION = 4, + ERROR_MIX_CHANNEL_CREATION = 8, + ERROR_MUSIC_CHANNEL_CREATION = 16, + ERROR_LOADING_XM = 32, + ERROR_LOADING_MOD = 64, + ERROR_LOADING_WAV = 128, + ERROR_LOADING_OGG = 256, + ERROR_OUT_OF_MIX_CHANNELS = 512, + ERROR_EXTENSION_NOT_RECOGNIZED = 1024, + ERROR_UNABLE_TO_OPEN_RRES_FILE = 2048, + ERROR_INVALID_RRES_FILE = 4096, + ERROR_INVALID_RRES_RESOURCE = 8192, + ERROR_UNINITIALIZED_CHANNELS = 16384 } AudioError; // Sound source type -- cgit v1.2.3 From cf6d2e39852b4e73479369a383ab3666189ee23f Mon Sep 17 00:00:00 2001 From: raysan5 Date: Thu, 2 Jun 2016 17:12:31 +0200 Subject: Review coding style to match raylib style Moved AudioError enum inside audio.c --- src/audio.c | 363 ++++++++++++++++++++++++++++++++--------------------------- src/audio.h | 20 +--- src/raylib.h | 23 +--- 3 files changed, 199 insertions(+), 207 deletions(-) (limited to 'src/raylib.h') diff --git a/src/audio.c b/src/audio.c index 452459ef..361b8b55 100644 --- a/src/audio.c +++ b/src/audio.c @@ -35,29 +35,29 @@ #include "raylib.h" #endif -#include "AL/al.h" // OpenAL basic header -#include "AL/alc.h" // OpenAL context header (like OpenGL, OpenAL requires a context to work) -#include "AL/alext.h" // OpenAL extensions for other format types +#include "AL/al.h" // OpenAL basic header +#include "AL/alc.h" // OpenAL context header (like OpenGL, OpenAL requires a context to work) +#include "AL/alext.h" // OpenAL extensions for other format types -#include // Required for: malloc(), free() -#include // Required for: strcmp(), strncmp() -#include // Required for: FILE, fopen(), fclose(), fread() +#include // Required for: malloc(), free() +#include // Required for: strcmp(), strncmp() +#include // Required for: FILE, fopen(), fclose(), fread() #if defined(AUDIO_STANDALONE) - #include // Required for: va_list, va_start(), vfprintf(), va_end() + #include // Required for: va_list, va_start(), vfprintf(), va_end() #else - #include "utils.h" // Required for: DecompressData() - // NOTE: Includes Android fopen() function map + #include "utils.h" // Required for: DecompressData() + // NOTE: Includes Android fopen() function map #endif //#define STB_VORBIS_HEADER_ONLY -#include "stb_vorbis.h" // OGG loading functions +#include "stb_vorbis.h" // OGG loading functions #define JAR_XM_IMPLEMENTATION -#include "jar_xm.h" // XM loading functions +#include "jar_xm.h" // XM loading functions #define JAR_MOD_IMPLEMENTATION -#include "jar_mod.h" // For playing .mod files +#include "jar_mod.h" // MOD loading functions //---------------------------------------------------------------------------------- // Defines and Macros @@ -89,25 +89,45 @@ typedef struct MixChannel_t { unsigned char mixChannel; // 0-3 or mixA-mixD, each mix channel can receive up to one dedicated audio stream bool floatingPoint; // if false then the short datatype is used instead bool playing; // false if paused - ALenum alFormat; // openAL format specifier - ALuint alSource; // openAL source - ALuint alBuffer[MAX_STREAM_BUFFERS]; // openAL sample buffer + + ALenum alFormat; // OpenAL format specifier + ALuint alSource; // OpenAL source + ALuint alBuffer[MAX_STREAM_BUFFERS]; // OpenAL sample buffer } MixChannel_t; // Music type (file streaming from memory) // NOTE: Anything longer than ~10 seconds should be streamed into a mix channel... typedef struct Music { stb_vorbis *stream; - jar_xm_context_t *xmctx; // Stores jar_xm mixc, XM chiptune context - jar_mod_context_t modctx; // Stores mod chiptune context + jar_xm_context_t *xmctx; // XM chiptune context + jar_mod_context_t modctx; // MOD chiptune context MixChannel_t *mixc; // mix channel unsigned int totalSamplesLeft; float totalLengthSeconds; bool loop; - bool chipTune; // True if chiptune is loaded + bool chipTune; // chiptune is loaded? } Music; +// Audio errors registered +typedef enum { + ERROR_RAW_CONTEXT_CREATION = 1, + ERROR_XM_CONTEXT_CREATION = 2, + ERROR_MOD_CONTEXT_CREATION = 4, + ERROR_MIX_CHANNEL_CREATION = 8, + ERROR_MUSIC_CHANNEL_CREATION = 16, + ERROR_LOADING_XM = 32, + ERROR_LOADING_MOD = 64, + ERROR_LOADING_WAV = 128, + ERROR_LOADING_OGG = 256, + ERROR_OUT_OF_MIX_CHANNELS = 512, + ERROR_EXTENSION_NOT_RECOGNIZED = 1024, + ERROR_UNABLE_TO_OPEN_RRES_FILE = 2048, + ERROR_INVALID_RRES_FILE = 4096, + ERROR_INVALID_RRES_RESOURCE = 8192, + ERROR_UNINITIALIZED_CHANNELS = 16384 +} AudioError; + #if defined(AUDIO_STANDALONE) typedef enum { INFO = 0, ERROR, WARNING, DEBUG, OTHER } TraceLogType; #endif @@ -119,6 +139,8 @@ static MixChannel_t* mixChannels_g[MAX_MIX_CHANNELS]; // What mix channel static bool musicEnabled_g = false; static Music musicChannels_g[MAX_MUSIC_STREAMS]; // Current music loaded, up to two can play at the same time +static lastAudioError = 0; // Registers last audio error + //---------------------------------------------------------------------------------- // Module specific Functions Declaration //---------------------------------------------------------------------------------- @@ -129,10 +151,9 @@ static void UnloadWave(Wave wave); // Unload wave data static bool BufferMusicStream(int index, int numBuffers); // Fill music buffers with data static void EmptyMusicStream(int index); // Empty music buffers - -static MixChannel_t* InitMixChannel(unsigned short sampleRate, unsigned char mixChannel, unsigned char channels, bool floatingPoint); // For streaming into mix channels. -static void CloseMixChannel(MixChannel_t* mixc); // Frees mix channel -static int BufferMixChannel(MixChannel_t* mixc, void *data, int numberElements); // Pushes more audio data into mixc mix channel, if NULL is passed it pauses +static MixChannel_t *InitMixChannel(unsigned short sampleRate, unsigned char mixChannel, unsigned char channels, bool floatingPoint); // For streaming into mix channels. +static void CloseMixChannel(MixChannel_t *mixc); // Frees mix channel +static int BufferMixChannel(MixChannel_t *mixc, void *data, int numberElements); // Pushes more audio data into mixc mix channel, if NULL is passed it pauses static int FillAlBufferWithSilence(MixChannel_t *mixc, ALuint buffer); // Fill buffer with zeros, returns number processed static void ResampleShortToFloat(short *shorts, float *floats, unsigned short len); // Pass two arrays of the same legnth in static void ResampleByteToFloat(char *chars, float *floats, unsigned short len); // Pass two arrays of same length in @@ -153,13 +174,13 @@ void InitAudioDevice(void) // Open and initialize a device with default settings ALCdevice *device = alcOpenDevice(NULL); - if(!device) TraceLog(ERROR, "Audio device could not be opened"); + if (!device) TraceLog(ERROR, "Audio device could not be opened"); ALCcontext *context = alcCreateContext(device, NULL); - if(context == NULL || alcMakeContextCurrent(context) == ALC_FALSE) + if ((context == NULL) || (alcMakeContextCurrent(context) == ALC_FALSE)) { - if(context != NULL) alcDestroyContext(context); + if (context != NULL) alcDestroyContext(context); alcCloseDevice(device); @@ -177,11 +198,10 @@ void InitAudioDevice(void) // Close the audio device for all contexts void CloseAudioDevice(void) { - for(int index=0; index= MAX_MIX_CHANNELS) return NULL; - if(!IsAudioDeviceReady()) InitAudioDevice(); + if (mixChannel >= MAX_MIX_CHANNELS) return NULL; + if (!IsAudioDeviceReady()) InitAudioDevice(); - if(!mixChannels_g[mixChannel]){ - MixChannel_t *mixc = (MixChannel_t*)malloc(sizeof(MixChannel_t)); + if (!mixChannels_g[mixChannel]) + { + MixChannel_t *mixc = (MixChannel_t *)malloc(sizeof(MixChannel_t)); mixc->sampleRate = sampleRate; mixc->channels = channels; mixc->mixChannel = mixChannel; mixc->floatingPoint = floatingPoint; mixChannels_g[mixChannel] = mixc; - // setup openAL format - if(channels == 1) + // Setup OpenAL format + if (channels == 1) { - if(floatingPoint) - mixc->alFormat = AL_FORMAT_MONO_FLOAT32; - else - mixc->alFormat = AL_FORMAT_MONO16; + if (floatingPoint) mixc->alFormat = AL_FORMAT_MONO_FLOAT32; + else mixc->alFormat = AL_FORMAT_MONO16; } - else if(channels == 2) + else if (channels == 2) { - if(floatingPoint) - mixc->alFormat = AL_FORMAT_STEREO_FLOAT32; - else - mixc->alFormat = AL_FORMAT_STEREO16; + if (floatingPoint) mixc->alFormat = AL_FORMAT_STEREO_FLOAT32; + else mixc->alFormat = AL_FORMAT_STEREO16; } // Create an audio source @@ -253,10 +273,8 @@ static MixChannel_t* InitMixChannel(unsigned short sampleRate, unsigned char mix // Create Buffer alGenBuffers(MAX_STREAM_BUFFERS, mixc->alBuffer); - //fill buffers - int x; - for(x=0;xalBuffer[x]); + // Fill buffers + for (int i = 0; i < MAX_STREAM_BUFFERS; i++) FillAlBufferWithSilence(mixc, mixc->alBuffer[i]); alSourceQueueBuffers(mixc->alSource, MAX_STREAM_BUFFERS, mixc->alBuffer); mixc->playing = true; @@ -264,27 +282,30 @@ static MixChannel_t* InitMixChannel(unsigned short sampleRate, unsigned char mix return mixc; } + return NULL; } // Frees buffer in mix channel -static void CloseMixChannel(MixChannel_t* mixc) +static void CloseMixChannel(MixChannel_t *mixc) { - if(mixc){ + if (mixc) + { alSourceStop(mixc->alSource); mixc->playing = false; - //flush out all queued buffers + // Flush out all queued buffers ALuint buffer = 0; int queued = 0; alGetSourcei(mixc->alSource, AL_BUFFERS_QUEUED, &queued); + while (queued > 0) { alSourceUnqueueBuffers(mixc->alSource, 1, &buffer); queued--; } - //delete source and buffers + // Delete source and buffers alDeleteSources(1, &mixc->alSource); alDeleteBuffers(MAX_STREAM_BUFFERS, mixc->alBuffer); mixChannels_g[mixc->mixChannel] = NULL; @@ -296,39 +317,46 @@ static void CloseMixChannel(MixChannel_t* mixc) // Pushes more audio data into mixc mix channel, only one buffer per call // Call "BufferMixChannel(mixc, NULL, 0)" if you want to pause the audio. // @Returns number of samples that where processed. -static int BufferMixChannel(MixChannel_t* mixc, void *data, int numberElements) +static int BufferMixChannel(MixChannel_t *mixc, void *data, int numberElements) { - if(!mixc || mixChannels_g[mixc->mixChannel] != mixc) return 0; // when there is two channels there must be an even number of samples + if (!mixc || (mixChannels_g[mixc->mixChannel] != mixc)) return 0; // When there is two channels there must be an even number of samples - if (!data || !numberElements) - { // pauses audio until data is given - if(mixc->playing){ + if (!data || !numberElements) + { + // Pauses audio until data is given + if (mixc->playing) + { alSourcePause(mixc->alSource); mixc->playing = false; } + return 0; } - else if(!mixc->playing) - { // restart audio otherwise + else if (!mixc->playing) + { + // Restart audio otherwise alSourcePlay(mixc->alSource); mixc->playing = true; } - - + ALuint buffer = 0; alSourceUnqueueBuffers(mixc->alSource, 1, &buffer); - if(!buffer) return 0; - if(mixc->floatingPoint) // process float buffers + if (!buffer) return 0; + + if (mixc->floatingPoint) { - float *ptr = (float*)data; + // Process float buffers + float *ptr = (float *)data; alBufferData(buffer, mixc->alFormat, ptr, numberElements*sizeof(float), mixc->sampleRate); } - else // process short buffers + else { - short *ptr = (short*)data; + // Process short buffers + short *ptr = (short *)data; alBufferData(buffer, mixc->alFormat, ptr, numberElements*sizeof(short), mixc->sampleRate); } + alSourceQueueBuffers(mixc->alSource, 1, &buffer); return numberElements; @@ -337,15 +365,18 @@ static int BufferMixChannel(MixChannel_t* mixc, void *data, int numberElements) // fill buffer with zeros, returns number processed static int FillAlBufferWithSilence(MixChannel_t *mixc, ALuint buffer) { - if(mixc->floatingPoint){ - float pcm[MUSIC_BUFFER_SIZE_FLOAT] = {0.f}; + if (mixc->floatingPoint) + { + float pcm[MUSIC_BUFFER_SIZE_FLOAT] = { 0.0f }; alBufferData(buffer, mixc->alFormat, pcm, MUSIC_BUFFER_SIZE_FLOAT*sizeof(float), mixc->sampleRate); + return MUSIC_BUFFER_SIZE_FLOAT; } else { - short pcm[MUSIC_BUFFER_SIZE_SHORT] = {0}; + short pcm[MUSIC_BUFFER_SIZE_SHORT] = { 0 }; alBufferData(buffer, mixc->alFormat, pcm, MUSIC_BUFFER_SIZE_SHORT*sizeof(short), mixc->sampleRate); + return MUSIC_BUFFER_SIZE_SHORT; } } @@ -355,13 +386,10 @@ static int FillAlBufferWithSilence(MixChannel_t *mixc, ALuint buffer) // ResampleShortToFloat(sh,fl,3); static void ResampleShortToFloat(short *shorts, float *floats, unsigned short len) { - int x; - for(x=0;x= 0) + + if (ctx >= 0) { MixChannel_t* mixc = mixChannels_g[ctx]; numBuffered = BufferMixChannel(mixc, data, numberElements); } + return numBuffered; } - - - - //---------------------------------------------------------------------------------- // Module Functions Definition - Sounds loading and playing (.WAV) //---------------------------------------------------------------------------------- @@ -438,9 +458,12 @@ Sound LoadSound(char *fileName) if (strcmp(GetExtension(fileName),"wav") == 0) wave = LoadWAV(fileName); else if (strcmp(GetExtension(fileName),"ogg") == 0) wave = LoadOGG(fileName); - else{ + else + { TraceLog(WARNING, "[%s] Sound extension not recognized, it can't be loaded", fileName); - sound.error = ERROR_EXTENSION_NOT_RECOGNIZED; //error + + // TODO: Find a better way to register errors (similar to glGetError()) + lastAudioError = ERROR_EXTENSION_NOT_RECOGNIZED; } if (wave.data != NULL) @@ -568,7 +591,7 @@ Sound LoadSoundFromRES(const char *rresName, int resId) if (rresFile == NULL) { TraceLog(WARNING, "[%s] rRES raylib resource file could not be opened", rresName); - sound.error = ERROR_UNABLE_TO_OPEN_RRES_FILE; //error + lastAudioError = ERROR_UNABLE_TO_OPEN_RRES_FILE; } else { @@ -583,7 +606,7 @@ Sound LoadSoundFromRES(const char *rresName, int resId) if ((id[0] != 'r') && (id[1] != 'R') && (id[2] != 'E') &&(id[3] != 'S')) { TraceLog(WARNING, "[%s] This is not a valid raylib resource file", rresName); - sound.error = ERROR_INVALID_RRES_FILE; + lastAudioError = ERROR_INVALID_RRES_FILE; } else { @@ -674,7 +697,7 @@ Sound LoadSoundFromRES(const char *rresName, int resId) else { TraceLog(WARNING, "[%s] Required resource do not seem to be a valid SOUND resource", rresName); - sound.error = ERROR_INVALID_RRES_RESOURCE; + lastAudioError = ERROR_INVALID_RRES_RESOURCE; } } else @@ -780,12 +803,12 @@ int PlayMusicStream(int musicIndex, char *fileName) { int mixIndex; - if(musicChannels_g[musicIndex].stream || musicChannels_g[musicIndex].xmctx) return ERROR_UNINITIALIZED_CHANNELS; // error + if (musicChannels_g[musicIndex].stream || musicChannels_g[musicIndex].xmctx) return ERROR_UNINITIALIZED_CHANNELS; // error - for(mixIndex = 0; mixIndex < MAX_MIX_CHANNELS; mixIndex++) // find empty mix channel slot + for (mixIndex = 0; mixIndex < MAX_MIX_CHANNELS; mixIndex++) // find empty mix channel slot { - if(mixChannels_g[mixIndex] == NULL) break; - else if(mixIndex == MAX_MIX_CHANNELS - 1) return ERROR_OUT_OF_MIX_CHANNELS; // error + if (mixChannels_g[mixIndex] == NULL) break; + else if (mixIndex == (MAX_MIX_CHANNELS - 1)) return ERROR_OUT_OF_MIX_CHANNELS; // error } if (strcmp(GetExtension(fileName),"ogg") == 0) @@ -814,21 +837,24 @@ int PlayMusicStream(int musicIndex, char *fileName) musicChannels_g[musicIndex].totalSamplesLeft = (unsigned int)stb_vorbis_stream_length_in_samples(musicChannels_g[musicIndex].stream) * info.channels; musicChannels_g[musicIndex].totalLengthSeconds = stb_vorbis_stream_length_in_seconds(musicChannels_g[musicIndex].stream); - if (info.channels == 2){ + if (info.channels == 2) + { musicChannels_g[musicIndex].mixc = InitMixChannel(info.sample_rate, mixIndex, 2, false); musicChannels_g[musicIndex].mixc->playing = true; } - else{ + else + { musicChannels_g[musicIndex].mixc = InitMixChannel(info.sample_rate, mixIndex, 1, false); musicChannels_g[musicIndex].mixc->playing = true; } - if(!musicChannels_g[musicIndex].mixc) return ERROR_LOADING_OGG; // error + + if (!musicChannels_g[musicIndex].mixc) return ERROR_LOADING_OGG; // error } } else if (strcmp(GetExtension(fileName),"xm") == 0) { // only stereo is supported for xm - if(!jar_xm_create_context_from_file(&musicChannels_g[musicIndex].xmctx, 48000, fileName)) + if (!jar_xm_create_context_from_file(&musicChannels_g[musicIndex].xmctx, 48000, fileName)) { musicChannels_g[musicIndex].chipTune = true; musicChannels_g[musicIndex].loop = true; @@ -841,7 +867,9 @@ int PlayMusicStream(int musicIndex, char *fileName) TraceLog(INFO, "[%s] XM track length: %11.6f sec", fileName, musicChannels_g[musicIndex].totalLengthSeconds); musicChannels_g[musicIndex].mixc = InitMixChannel(48000, mixIndex, 2, true); - if(!musicChannels_g[musicIndex].mixc) return ERROR_XM_CONTEXT_CREATION; // error + + if (!musicChannels_g[musicIndex].mixc) return ERROR_XM_CONTEXT_CREATION; // error + musicChannels_g[musicIndex].mixc->playing = true; } else @@ -853,7 +881,8 @@ int PlayMusicStream(int musicIndex, char *fileName) else if (strcmp(GetExtension(fileName),"mod") == 0) { jar_mod_init(&musicChannels_g[musicIndex].modctx); - if(jar_mod_load_file(&musicChannels_g[musicIndex].modctx, fileName)) + + if (jar_mod_load_file(&musicChannels_g[musicIndex].modctx, fileName)) { musicChannels_g[musicIndex].chipTune = true; musicChannels_g[musicIndex].loop = true; @@ -865,7 +894,9 @@ int PlayMusicStream(int musicIndex, char *fileName) TraceLog(INFO, "[%s] MOD track length: %11.6f sec", fileName, musicChannels_g[musicIndex].totalLengthSeconds); musicChannels_g[musicIndex].mixc = InitMixChannel(48000, mixIndex, 2, false); - if(!musicChannels_g[musicIndex].mixc) return ERROR_MOD_CONTEXT_CREATION; // error + + if (!musicChannels_g[musicIndex].mixc) return ERROR_MOD_CONTEXT_CREATION; // error + musicChannels_g[musicIndex].mixc->playing = true; } else @@ -879,6 +910,7 @@ int PlayMusicStream(int musicIndex, char *fileName) TraceLog(WARNING, "[%s] Music extension not recognized, it can't be loaded", fileName); return ERROR_EXTENSION_NOT_RECOGNIZED; // error } + return 0; // normal return } @@ -894,17 +926,12 @@ void StopMusicStream(int index) jar_xm_free_context(musicChannels_g[index].xmctx); musicChannels_g[index].xmctx = 0; } - else if(musicChannels_g[index].chipTune && musicChannels_g[index].modctx.mod_loaded) - { - jar_mod_unload(&musicChannels_g[index].modctx); - } - else - { - stb_vorbis_close(musicChannels_g[index].stream); - } + else if (musicChannels_g[index].chipTune && musicChannels_g[index].modctx.mod_loaded) jar_mod_unload(&musicChannels_g[index].modctx); + else stb_vorbis_close(musicChannels_g[index].stream); - if(!getMusicStreamCount()) musicEnabled_g = false; - if(musicChannels_g[index].stream || musicChannels_g[index].xmctx) + if (!GetMusicStreamCount()) musicEnabled_g = false; + + if (musicChannels_g[index].stream || musicChannels_g[index].xmctx) { musicChannels_g[index].stream = NULL; musicChannels_g[index].xmctx = NULL; @@ -913,11 +940,15 @@ void StopMusicStream(int index) } //get number of music channels active at this time, this does not mean they are playing -int getMusicStreamCount(void) +int GetMusicStreamCount(void) { int musicCount = 0; - for(int musicIndex = 0; musicIndex < MAX_MUSIC_STREAMS; musicIndex++) // find empty music slot + + // Find empty music slot + for (int musicIndex = 0; musicIndex < MAX_MUSIC_STREAMS; musicIndex++) + { if(musicChannels_g[musicIndex].stream != NULL || musicChannels_g[musicIndex].chipTune) musicCount++; + } return musicCount; } @@ -939,8 +970,11 @@ void ResumeMusicStream(int index) { // Resume music playing... if music available! ALenum state; - if(index < MAX_MUSIC_STREAMS && musicChannels_g[index].mixc){ + + if (index < MAX_MUSIC_STREAMS && musicChannels_g[index].mixc) + { alGetSourcei(musicChannels_g[index].mixc->alSource, AL_SOURCE_STATE, &state); + if (state == AL_PAUSED) { TraceLog(INFO, "Resuming music stream"); @@ -956,8 +990,10 @@ bool IsMusicPlaying(int index) bool playing = false; ALint state; - if(index < MAX_MUSIC_STREAMS && musicChannels_g[index].mixc){ + if (index < MAX_MUSIC_STREAMS && musicChannels_g[index].mixc) + { alGetSourcei(musicChannels_g[index].mixc->alSource, AL_SOURCE_STATE, &state); + if (state == AL_PLAYING) playing = true; } @@ -967,14 +1003,17 @@ bool IsMusicPlaying(int index) // Set volume for music void SetMusicVolume(int index, float volume) { - if(index < MAX_MUSIC_STREAMS && musicChannels_g[index].mixc){ + if (index < MAX_MUSIC_STREAMS && musicChannels_g[index].mixc) + { alSourcef(musicChannels_g[index].mixc->alSource, AL_GAIN, volume); } } +// Set pitch for music void SetMusicPitch(int index, float pitch) { - if(index < MAX_MUSIC_STREAMS && musicChannels_g[index].mixc){ + if (index < MAX_MUSIC_STREAMS && musicChannels_g[index].mixc) + { alSourcef(musicChannels_g[index].mixc->alSource, AL_PITCH, pitch); } } @@ -983,14 +1022,9 @@ void SetMusicPitch(int index, float pitch) float GetMusicTimeLength(int index) { float totalSeconds; - if (musicChannels_g[index].chipTune) - { - totalSeconds = (float)musicChannels_g[index].totalLengthSeconds; - } - else - { - totalSeconds = stb_vorbis_stream_length_in_seconds(musicChannels_g[index].stream); - } + + if (musicChannels_g[index].chipTune) totalSeconds = (float)musicChannels_g[index].totalLengthSeconds; + else totalSeconds = stb_vorbis_stream_length_in_seconds(musicChannels_g[index].stream); return totalSeconds; } @@ -999,7 +1033,8 @@ float GetMusicTimeLength(int index) float GetMusicTimePlayed(int index) { float secondsPlayed = 0.0f; - if(index < MAX_MUSIC_STREAMS && musicChannels_g[index].mixc) + + if (index < MAX_MUSIC_STREAMS && musicChannels_g[index].mixc) { if (musicChannels_g[index].chipTune && musicChannels_g[index].xmctx) { @@ -1033,33 +1068,33 @@ static bool BufferMusicStream(int index, int numBuffers) short pcm[MUSIC_BUFFER_SIZE_SHORT]; float pcmf[MUSIC_BUFFER_SIZE_FLOAT]; - int size = 0; // Total size of data steamed in L+R samples for xm floats, individual L or R for ogg shorts - bool active = true; // We can get more data from stream (not finished) + int size = 0; // Total size of data steamed in L+R samples for xm floats, individual L or R for ogg shorts + bool active = true; // We can get more data from stream (not finished) if (musicChannels_g[index].chipTune) // There is no end of stream for xmfiles, once the end is reached zeros are generated for non looped chiptunes. { - for(int x=0; x= MUSIC_BUFFER_SIZE_SHORT) - size = MUSIC_BUFFER_SIZE_SHORT / 2; - else - size = musicChannels_g[index].totalSamplesLeft / 2; + if (musicChannels_g[index].modctx.mod_loaded) + { + if (musicChannels_g[index].totalSamplesLeft >= MUSIC_BUFFER_SIZE_SHORT) size = MUSIC_BUFFER_SIZE_SHORT/2; + else size = musicChannels_g[index].totalSamplesLeft/2; + jar_mod_fillbuffer(&musicChannels_g[index].modctx, pcm, size, 0 ); - BufferMixChannel(musicChannels_g[index].mixc, pcm, size * 2); + BufferMixChannel(musicChannels_g[index].mixc, pcm, size*2); } - else if(musicChannels_g[index].xmctx){ - if(musicChannels_g[index].totalSamplesLeft >= MUSIC_BUFFER_SIZE_FLOAT) - size = MUSIC_BUFFER_SIZE_FLOAT / 2; - else - size = musicChannels_g[index].totalSamplesLeft / 2; + else if (musicChannels_g[index].xmctx) + { + if (musicChannels_g[index].totalSamplesLeft >= MUSIC_BUFFER_SIZE_FLOAT) size = MUSIC_BUFFER_SIZE_FLOAT/2; + else size = musicChannels_g[index].totalSamplesLeft/2; + jar_xm_generate_samples(musicChannels_g[index].xmctx, pcmf, size); // reads 2*readlen shorts and moves them to buffer+size memory location - BufferMixChannel(musicChannels_g[index].mixc, pcmf, size * 2); + BufferMixChannel(musicChannels_g[index].mixc, pcmf, size*2); } - musicChannels_g[index].totalSamplesLeft -= size; - if(musicChannels_g[index].totalSamplesLeft <= 0) + + if (musicChannels_g[index].totalSamplesLeft <= 0) { active = false; break; @@ -1068,17 +1103,16 @@ static bool BufferMusicStream(int index, int numBuffers) } else { - if(musicChannels_g[index].totalSamplesLeft >= MUSIC_BUFFER_SIZE_SHORT) - size = MUSIC_BUFFER_SIZE_SHORT; - else - size = musicChannels_g[index].totalSamplesLeft; + if (musicChannels_g[index].totalSamplesLeft >= MUSIC_BUFFER_SIZE_SHORT) size = MUSIC_BUFFER_SIZE_SHORT; + else size = musicChannels_g[index].totalSamplesLeft; - for(int x=0; xchannels, pcm, size); BufferMixChannel(musicChannels_g[index].mixc, pcm, streamedBytes * musicChannels_g[index].mixc->channels); musicChannels_g[index].totalSamplesLeft -= streamedBytes * musicChannels_g[index].mixc->channels; - if(musicChannels_g[index].totalSamplesLeft <= 0) + + if (musicChannels_g[index].totalSamplesLeft <= 0) { active = false; break; @@ -1105,7 +1139,7 @@ static void EmptyMusicStream(int index) } } -//determine if a music stream is ready to be written to +// Determine if a music stream is ready to be written static int IsMusicStreamReadyForBuffering(int index) { ALint processed = 0; @@ -1120,7 +1154,7 @@ void UpdateMusicStream(int index) bool active = true; int numBuffers = IsMusicStreamReadyForBuffering(index); - if (musicChannels_g[index].mixc->playing && index < MAX_MUSIC_STREAMS && musicEnabled_g && musicChannels_g[index].mixc && numBuffers) + if (musicChannels_g[index].mixc->playing && (index < MAX_MUSIC_STREAMS) && musicEnabled_g && musicChannels_g[index].mixc && numBuffers) { active = BufferMusicStream(index, numBuffers); @@ -1136,9 +1170,9 @@ void UpdateMusicStream(int index) stb_vorbis_seek_start(musicChannels_g[index].stream); musicChannels_g[index].totalSamplesLeft = stb_vorbis_stream_length_in_samples(musicChannels_g[index].stream) * musicChannels_g[index].mixc->channels; } + active = true; } - if (alGetError() != AL_NO_ERROR) TraceLog(WARNING, "Error buffering data..."); @@ -1149,9 +1183,6 @@ void UpdateMusicStream(int index) if (!active) StopMusicStream(index); } - else - return; - } // Load WAV file into Wave structure diff --git a/src/audio.h b/src/audio.h index a7475566..e30087ba 100644 --- a/src/audio.h +++ b/src/audio.h @@ -47,24 +47,6 @@ #endif #endif -typedef enum { - ERROR_RAW_CONTEXT_CREATION = 1, - ERROR_XM_CONTEXT_CREATION = 2, - ERROR_MOD_CONTEXT_CREATION = 4, - ERROR_MIX_CHANNEL_CREATION = 8, - ERROR_MUSIC_CHANNEL_CREATION = 16, - ERROR_LOADING_XM = 32, - ERROR_LOADING_MOD = 64, - ERROR_LOADING_WAV = 128, - ERROR_LOADING_OGG = 256, - ERROR_OUT_OF_MIX_CHANNELS = 512, - ERROR_EXTENSION_NOT_RECOGNIZED = 1024, - ERROR_UNABLE_TO_OPEN_RRES_FILE = 2048, - ERROR_INVALID_RRES_FILE = 4096, - ERROR_INVALID_RRES_RESOURCE = 8192, - ERROR_UNINITIALIZED_CHANNELS = 16384 -} AudioError; - // Sound source type typedef struct Sound { unsigned int source; @@ -120,7 +102,7 @@ bool IsMusicPlaying(int index); // Check if musi void SetMusicVolume(int index, float volume); // Set volume for music (1.0 is max level) float GetMusicTimeLength(int index); // Get music time length (in seconds) float GetMusicTimePlayed(int index); // Get current music time played (in seconds) -int getMusicStreamCount(void); +int GetMusicStreamCount(void); void SetMusicPitch(int index, float pitch); // used to output raw audio streams, returns negative numbers on error diff --git a/src/raylib.h b/src/raylib.h index 21892d68..97f4a2e6 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -452,29 +452,10 @@ typedef struct Ray { Vector3 direction; } Ray; -typedef enum { // allows errors to be & together - ERROR_RAW_CONTEXT_CREATION = 1, - ERROR_XM_CONTEXT_CREATION = 2, - ERROR_MOD_CONTEXT_CREATION = 4, - ERROR_MIX_CHANNEL_CREATION = 8, - ERROR_MUSIC_CHANNEL_CREATION = 16, - ERROR_LOADING_XM = 32, - ERROR_LOADING_MOD = 64, - ERROR_LOADING_WAV = 128, - ERROR_LOADING_OGG = 256, - ERROR_OUT_OF_MIX_CHANNELS = 512, - ERROR_EXTENSION_NOT_RECOGNIZED = 1024, - ERROR_UNABLE_TO_OPEN_RRES_FILE = 2048, - ERROR_INVALID_RRES_FILE = 4096, - ERROR_INVALID_RRES_RESOURCE = 8192, - ERROR_UNINITIALIZED_CHANNELS = 16384 -} AudioError; - // Sound source type typedef struct Sound { unsigned int source; unsigned int buffer; - AudioError error; // if there was any error during the creation or use of this Sound } Sound; // Wave type, defines audio wave data @@ -488,8 +469,6 @@ typedef struct Wave { typedef int RawAudioContext; - - // Texture formats // NOTE: Support depends on OpenGL version and platform typedef enum { @@ -940,7 +919,7 @@ bool IsMusicPlaying(int index); // Check if musi void SetMusicVolume(int index, float volume); // Set volume for music (1.0 is max level) float GetMusicTimeLength(int index); // Get current music time length (in seconds) float GetMusicTimePlayed(int index); // Get current music time played (in seconds) -int getMusicStreamCount(void); +int GetMusicStreamCount(void); void SetMusicPitch(int index, float pitch); // used to output raw audio streams, returns negative numbers on error -- cgit v1.2.3 From cafc66a3c18ae4b8adf2673dfecda1ad3604aaee Mon Sep 17 00:00:00 2001 From: raysan5 Date: Thu, 2 Jun 2016 19:09:56 +0200 Subject: Rename for consistency with other functions --- src/audio.c | 70 ++++++++++++++++++++++++++++++------------------------------ src/audio.h | 2 +- src/raylib.h | 2 +- 3 files changed, 37 insertions(+), 37 deletions(-) (limited to 'src/raylib.h') diff --git a/src/audio.c b/src/audio.c index 31ecd879..b5514b12 100644 --- a/src/audio.c +++ b/src/audio.c @@ -799,11 +799,11 @@ void SetSoundPitch(Sound sound, float pitch) // Start music playing (open stream) // returns 0 on success -int PlayMusicStream(int musicIndex, char *fileName) +int PlayMusicStream(int index, char *fileName) { int mixIndex; - if (musicChannels_g[musicIndex].stream || musicChannels_g[musicIndex].xmctx) return ERROR_UNINITIALIZED_CHANNELS; // error + if (musicChannels_g[index].stream || musicChannels_g[index].xmctx) return ERROR_UNINITIALIZED_CHANNELS; // error for (mixIndex = 0; mixIndex < MAX_MIX_CHANNELS; mixIndex++) // find empty mix channel slot { @@ -814,9 +814,9 @@ int PlayMusicStream(int musicIndex, char *fileName) if (strcmp(GetExtension(fileName),"ogg") == 0) { // Open audio stream - musicChannels_g[musicIndex].stream = stb_vorbis_open_filename(fileName, NULL, NULL); + musicChannels_g[index].stream = stb_vorbis_open_filename(fileName, NULL, NULL); - if (musicChannels_g[musicIndex].stream == NULL) + if (musicChannels_g[index].stream == NULL) { TraceLog(WARNING, "[%s] OGG audio file could not be opened", fileName); return ERROR_LOADING_OGG; // error @@ -824,53 +824,53 @@ int PlayMusicStream(int musicIndex, char *fileName) else { // Get file info - stb_vorbis_info info = stb_vorbis_get_info(musicChannels_g[musicIndex].stream); + stb_vorbis_info info = stb_vorbis_get_info(musicChannels_g[index].stream); TraceLog(INFO, "[%s] Ogg sample rate: %i", fileName, info.sample_rate); TraceLog(INFO, "[%s] Ogg channels: %i", fileName, info.channels); TraceLog(DEBUG, "[%s] Temp memory required: %i", fileName, info.temp_memory_required); - musicChannels_g[musicIndex].loop = true; // We loop by default + musicChannels_g[index].loop = true; // We loop by default musicEnabled_g = true; - musicChannels_g[musicIndex].totalSamplesLeft = (unsigned int)stb_vorbis_stream_length_in_samples(musicChannels_g[musicIndex].stream) * info.channels; - musicChannels_g[musicIndex].totalLengthSeconds = stb_vorbis_stream_length_in_seconds(musicChannels_g[musicIndex].stream); + musicChannels_g[index].totalSamplesLeft = (unsigned int)stb_vorbis_stream_length_in_samples(musicChannels_g[index].stream) * info.channels; + musicChannels_g[index].totalLengthSeconds = stb_vorbis_stream_length_in_seconds(musicChannels_g[index].stream); if (info.channels == 2) { - musicChannels_g[musicIndex].mixc = InitMixChannel(info.sample_rate, mixIndex, 2, false); - musicChannels_g[musicIndex].mixc->playing = true; + musicChannels_g[index].mixc = InitMixChannel(info.sample_rate, mixIndex, 2, false); + musicChannels_g[index].mixc->playing = true; } else { - musicChannels_g[musicIndex].mixc = InitMixChannel(info.sample_rate, mixIndex, 1, false); - musicChannels_g[musicIndex].mixc->playing = true; + musicChannels_g[index].mixc = InitMixChannel(info.sample_rate, mixIndex, 1, false); + musicChannels_g[index].mixc->playing = true; } - if (!musicChannels_g[musicIndex].mixc) return ERROR_LOADING_OGG; // error + if (!musicChannels_g[index].mixc) return ERROR_LOADING_OGG; // error } } else if (strcmp(GetExtension(fileName),"xm") == 0) { // only stereo is supported for xm - if (!jar_xm_create_context_from_file(&musicChannels_g[musicIndex].xmctx, 48000, fileName)) + if (!jar_xm_create_context_from_file(&musicChannels_g[index].xmctx, 48000, fileName)) { - musicChannels_g[musicIndex].chipTune = true; - musicChannels_g[musicIndex].loop = true; - jar_xm_set_max_loop_count(musicChannels_g[musicIndex].xmctx, 0); // infinite number of loops - musicChannels_g[musicIndex].totalSamplesLeft = (unsigned int)jar_xm_get_remaining_samples(musicChannels_g[musicIndex].xmctx); - musicChannels_g[musicIndex].totalLengthSeconds = ((float)musicChannels_g[musicIndex].totalSamplesLeft) / 48000.f; + musicChannels_g[index].chipTune = true; + musicChannels_g[index].loop = true; + jar_xm_set_max_loop_count(musicChannels_g[index].xmctx, 0); // infinite number of loops + musicChannels_g[index].totalSamplesLeft = (unsigned int)jar_xm_get_remaining_samples(musicChannels_g[index].xmctx); + musicChannels_g[index].totalLengthSeconds = ((float)musicChannels_g[index].totalSamplesLeft) / 48000.f; musicEnabled_g = true; - TraceLog(INFO, "[%s] XM number of samples: %i", fileName, musicChannels_g[musicIndex].totalSamplesLeft); - TraceLog(INFO, "[%s] XM track length: %11.6f sec", fileName, musicChannels_g[musicIndex].totalLengthSeconds); + TraceLog(INFO, "[%s] XM number of samples: %i", fileName, musicChannels_g[index].totalSamplesLeft); + TraceLog(INFO, "[%s] XM track length: %11.6f sec", fileName, musicChannels_g[index].totalLengthSeconds); - musicChannels_g[musicIndex].mixc = InitMixChannel(48000, mixIndex, 2, true); + musicChannels_g[index].mixc = InitMixChannel(48000, mixIndex, 2, true); - if (!musicChannels_g[musicIndex].mixc) return ERROR_XM_CONTEXT_CREATION; // error + if (!musicChannels_g[index].mixc) return ERROR_XM_CONTEXT_CREATION; // error - musicChannels_g[musicIndex].mixc->playing = true; + musicChannels_g[index].mixc->playing = true; } else { @@ -880,24 +880,24 @@ int PlayMusicStream(int musicIndex, char *fileName) } else if (strcmp(GetExtension(fileName),"mod") == 0) { - jar_mod_init(&musicChannels_g[musicIndex].modctx); + jar_mod_init(&musicChannels_g[index].modctx); - if (jar_mod_load_file(&musicChannels_g[musicIndex].modctx, fileName)) + if (jar_mod_load_file(&musicChannels_g[index].modctx, fileName)) { - musicChannels_g[musicIndex].chipTune = true; - musicChannels_g[musicIndex].loop = true; - musicChannels_g[musicIndex].totalSamplesLeft = (unsigned int)jar_mod_max_samples(&musicChannels_g[musicIndex].modctx); - musicChannels_g[musicIndex].totalLengthSeconds = ((float)musicChannels_g[musicIndex].totalSamplesLeft) / 48000.f; + musicChannels_g[index].chipTune = true; + musicChannels_g[index].loop = true; + musicChannels_g[index].totalSamplesLeft = (unsigned int)jar_mod_max_samples(&musicChannels_g[index].modctx); + musicChannels_g[index].totalLengthSeconds = ((float)musicChannels_g[index].totalSamplesLeft) / 48000.f; musicEnabled_g = true; - TraceLog(INFO, "[%s] MOD number of samples: %i", fileName, musicChannels_g[musicIndex].totalSamplesLeft); - TraceLog(INFO, "[%s] MOD track length: %11.6f sec", fileName, musicChannels_g[musicIndex].totalLengthSeconds); + TraceLog(INFO, "[%s] MOD number of samples: %i", fileName, musicChannels_g[index].totalSamplesLeft); + TraceLog(INFO, "[%s] MOD track length: %11.6f sec", fileName, musicChannels_g[index].totalLengthSeconds); - musicChannels_g[musicIndex].mixc = InitMixChannel(48000, mixIndex, 2, false); + musicChannels_g[index].mixc = InitMixChannel(48000, mixIndex, 2, false); - if (!musicChannels_g[musicIndex].mixc) return ERROR_MOD_CONTEXT_CREATION; // error + if (!musicChannels_g[index].mixc) return ERROR_MOD_CONTEXT_CREATION; // error - musicChannels_g[musicIndex].mixc->playing = true; + musicChannels_g[index].mixc->playing = true; } else { diff --git a/src/audio.h b/src/audio.h index e30087ba..fe72d866 100644 --- a/src/audio.h +++ b/src/audio.h @@ -93,7 +93,7 @@ bool IsSoundPlaying(Sound sound); // Check if a so void SetSoundVolume(Sound sound, float volume); // Set volume for a sound (1.0 is max level) void SetSoundPitch(Sound sound, float pitch); // Set pitch for a sound (1.0 is base level) -int PlayMusicStream(int musicIndex, char *fileName); // Start music playing (open stream) +int PlayMusicStream(int index, char *fileName); // Start music playing (open stream) void UpdateMusicStream(int index); // Updates buffers for music streaming void StopMusicStream(int index); // Stop music playing (close stream) void PauseMusicStream(int index); // Pause music playing diff --git a/src/raylib.h b/src/raylib.h index 97f4a2e6..bc2f658f 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -910,7 +910,7 @@ bool IsSoundPlaying(Sound sound); // Check if a so void SetSoundVolume(Sound sound, float volume); // Set volume for a sound (1.0 is max level) void SetSoundPitch(Sound sound, float pitch); // Set pitch for a sound (1.0 is base level) -int PlayMusicStream(int musicIndex, char *fileName); // Start music playing (open stream) +int PlayMusicStream(int index, char *fileName); // Start music playing (open stream) void UpdateMusicStream(int index); // Updates buffers for music streaming void StopMusicStream(int index); // Stop music playing (close stream) void PauseMusicStream(int index); // Pause music playing -- cgit v1.2.3 From 2168d8aa1af1e60467983099c5f72b7ac5ab5144 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Thu, 2 Jun 2016 19:16:11 +0200 Subject: Removed DrawPhysicObjectInfo() function To avoid additional dependencies --- src/physac.c | 16 ---------------- src/physac.h | 1 - src/raylib.h | 1 - 3 files changed, 18 deletions(-) (limited to 'src/raylib.h') diff --git a/src/physac.c b/src/physac.c index eed2f26e..1d577d3d 100644 --- a/src/physac.c +++ b/src/physac.c @@ -570,22 +570,6 @@ Rectangle TransformToRectangle(Transform transform) return (Rectangle){transform.position.x, transform.position.y, transform.scale.x, transform.scale.y}; } -// Draw physic object information at screen position -void DrawPhysicObjectInfo(PhysicObject pObj, Vector2 position, int fontSize) -{ - // Draw physic object ID - DrawText(FormatText("PhysicObject ID: %i - Enabled: %i", pObj->id, pObj->enabled), position.x, position.y, fontSize, BLACK); - - // Draw physic object transform values - DrawText(FormatText("\nTRANSFORM\nPosition: %f, %f\nRotation: %f\nScale: %f, %f", pObj->transform.position.x, pObj->transform.position.y, pObj->transform.rotation, pObj->transform.scale.x, pObj->transform.scale.y), position.x, position.y, fontSize, BLACK); - - // Draw physic object rigidbody values - DrawText(FormatText("\n\n\n\n\n\nRIGIDBODY\nEnabled: %i\nMass: %f\nAcceleration: %f, %f\nVelocity: %f, %f\nApplyGravity: %i\nIsGrounded: %i\nFriction: %f\nBounciness: %f", pObj->rigidbody.enabled, pObj->rigidbody.mass, pObj->rigidbody.acceleration.x, pObj->rigidbody.acceleration.y, - pObj->rigidbody.velocity.x, pObj->rigidbody.velocity.y, pObj->rigidbody.applyGravity, pObj->rigidbody.isGrounded, pObj->rigidbody.friction, pObj->rigidbody.bounciness), position.x, position.y, fontSize, BLACK); - - DrawText(FormatText("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nCOLLIDER\nEnabled: %i\nBounds: %i, %i, %i, %i\nRadius: %i", pObj->collider.enabled, pObj->collider.bounds.x, pObj->collider.bounds.y, pObj->collider.bounds.width, pObj->collider.bounds.height, pObj->collider.radius), position.x, position.y, fontSize, BLACK); -} - //---------------------------------------------------------------------------------- // Module specific Functions Definition //---------------------------------------------------------------------------------- diff --git a/src/physac.h b/src/physac.h index 6cef480a..b2ae2766 100644 --- a/src/physac.h +++ b/src/physac.h @@ -92,7 +92,6 @@ void ApplyForce(PhysicObject pObj, Vector2 force); void ApplyForceAtPosition(Vector2 position, float force, float radius); // Apply radial force to all physic objects in range Rectangle TransformToRectangle(Transform transform); // Convert Transform data type to Rectangle (position and scale) -void DrawPhysicObjectInfo(PhysicObject pObj, Vector2 position, int fontSize); // Draw physic object information at screen position #ifdef __cplusplus } diff --git a/src/raylib.h b/src/raylib.h index bc2f658f..a00c0ff9 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -890,7 +890,6 @@ void ApplyForce(PhysicObject pObj, Vector2 force); void ApplyForceAtPosition(Vector2 position, float force, float radius); // Apply radial force to all physic objects in range Rectangle TransformToRectangle(Transform transform); // Convert Transform data type to Rectangle (position and scale) -void DrawPhysicObjectInfo(PhysicObject pObj, Vector2 position, int fontSize); // Draw physic object information at screen position //------------------------------------------------------------------------------------ // Audio Loading and Playing Functions (Module: audio) -- cgit v1.2.3 From 0bc71d84f8ca2b8cbe48eae8769fb16958b98531 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Thu, 2 Jun 2016 20:23:09 +0200 Subject: Added functions to customize internal matrix Internal modelview and projection matrices can be replaced before drawing. --- src/raylib.h | 3 +++ src/raymath.h | 5 ++--- src/rlgl.c | 25 ++++++++++++++++++------- src/rlgl.h | 3 +++ 4 files changed, 26 insertions(+), 10 deletions(-) (limited to 'src/raylib.h') diff --git a/src/raylib.h b/src/raylib.h index a00c0ff9..efd96a67 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -868,6 +868,9 @@ void SetShaderValue(Shader shader, int uniformLoc, float *value, int size); // S void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size); // Set shader uniform value (int) void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat); // Set shader uniform value (matrix 4x4) +void SetMatrixProjection(Matrix proj); // Set a custom projection matrix (replaces internal projection matrix) +void SetMatrixModelview(Matrix view); // Set a custom modelview matrix (replaces internal modelview matrix) + void BeginShaderMode(Shader shader); // Begin custom shader drawing void EndShaderMode(void); // End custom shader drawing (use default shader) void BeginBlendMode(int mode); // Begin blending mode (alpha, additive, multiplied) diff --git a/src/raymath.h b/src/raymath.h index 188bd610..4075a1a9 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -339,15 +339,14 @@ RMDEF Vector3 VectorReflect(Vector3 vector, Vector3 normal) return result; } -// Transforms a Vector3 with a given Matrix +// Transforms a Vector3 by a given Matrix +// TODO: Review math (matrix transpose required?) RMDEF void VectorTransform(Vector3 *v, Matrix mat) { float x = v->x; float y = v->y; float z = v->z; - //MatrixTranspose(&mat); - v->x = mat.m0*x + mat.m4*y + mat.m8*z + mat.m12; v->y = mat.m1*x + mat.m5*y + mat.m9*z + mat.m13; v->z = mat.m2*x + mat.m6*y + mat.m10*z + mat.m14; diff --git a/src/rlgl.c b/src/rlgl.c index cfa6e2e6..6beececb 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -28,7 +28,7 @@ #include "rlgl.h" -#include // Standard input / output lib +#include // Required for: fopen(), fclose(), fread()... [Used only on ReadTextFile()] #include // Required for: malloc(), free(), rand() #include // Required for: strcmp(), strlen(), strtok() @@ -59,8 +59,8 @@ #endif #if defined(RLGL_STANDALONE) - #include // Required for: va_list, va_start(), vfprintf(), va_end() -#endif // NOTE: Used on TraceLog() + #include // Required for: va_list, va_start(), vfprintf(), va_end() [Used only on TraceLog()] +#endif //---------------------------------------------------------------------------------- // Defines and Macros @@ -355,7 +355,6 @@ void rlRotatef(float angleDeg, float x, float y, float z) Vector3 axis = (Vector3){ x, y, z }; VectorNormalize(&axis); matRotation = MatrixRotate(axis, angleDeg*DEG2RAD); - MatrixTranspose(&matRotation); *currentMatrix = MatrixMultiply(*currentMatrix, matRotation); @@ -2153,7 +2152,7 @@ void UnloadShader(Shader shader) } } -// Set custom shader to be used on batch draw +// Begin custom shader mode void BeginShaderMode(Shader shader) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) @@ -2165,7 +2164,7 @@ void BeginShaderMode(Shader shader) #endif } -// Set default shader to be used in batch draw +// End custom shader mode (returns to default shader) void EndShaderMode(void) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) @@ -2251,6 +2250,18 @@ void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat) #endif } +// Set a custom projection matrix (replaces internal projection matrix) +void SetMatrixProjection(Matrix proj) +{ + projection = proj; +} + +// Set a custom modelview matrix (replaces internal modelview matrix) +void SetMatrixModelview(Matrix view) +{ + modelview = view; +} + // Begin blending mode (alpha, additive, multiplied) // NOTE: Only 3 blending modes supported, default blend mode is alpha void BeginBlendMode(int mode) @@ -3068,7 +3079,7 @@ static void UnloadDefaultBuffers(void) free(quads.indices); } -// Sets shader uniform values for lights array +// Setup shader uniform values for lights array // NOTE: It would be far easier with shader UBOs but are not supported on OpenGL ES 2.0f static void SetShaderLights(Shader shader) { diff --git a/src/rlgl.h b/src/rlgl.h index 00482d2e..2a578a1f 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -329,6 +329,9 @@ void SetShaderValue(Shader shader, int uniformLoc, float *value, int size); // S void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size); // Set shader uniform value (int) void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat); // Set shader uniform value (matrix 4x4) +void SetMatrixProjection(Matrix proj); // Set a custom projection matrix (replaces internal projection matrix) +void SetMatrixModelview(Matrix view); // Set a custom modelview matrix (replaces internal modelview matrix) + void BeginShaderMode(Shader shader); // Begin custom shader drawing void EndShaderMode(void); // End custom shader drawing (use default shader) void BeginBlendMode(int mode); // Begin blending mode (alpha, additive, multiplied) -- cgit v1.2.3 From 13bef7aa0215c135074947a28dce92695d456565 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Fri, 3 Jun 2016 18:26:59 +0200 Subject: Work on Oculus functionality Trying to find the best way to integrate Oculus support into raylib, making it easy for the user... --- src/core.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----- src/raylib.h | 6 ++++++ 2 files changed, 63 insertions(+), 5 deletions(-) (limited to 'src/raylib.h') diff --git a/src/core.c b/src/core.c index d4db5017..7316c79c 100644 --- a/src/core.c +++ b/src/core.c @@ -483,11 +483,6 @@ void CloseWindow(void) { UnloadDefaultFont(); -#if defined(PLATFORM_OCULUS) - UnloadOculusMirror(session, mirror); // Unload Oculus mirror buffer - UnloadOculusBuffer(session, buffer); // Unload Oculus texture buffers -#endif - rlglClose(); // De-init rlgl #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) @@ -526,6 +521,63 @@ void CloseWindow(void) TraceLog(INFO, "Window closed successfully"); } +#if defined(PLATFORM_OCULUS) +// Init Oculus Rift device +// NOTE: Device initialization should be done before window creation? +void InitOculusDevice(void) +{ + ovrResult result = ovr_Initialize(NULL); + if (OVR_FAILURE(result)) TraceLog(ERROR, "OVR: Could not initialize Oculus device"); + + result = ovr_Create(&session, &luid); + if (OVR_FAILURE(result)) + { + TraceLog(WARNING, "OVR: Could not create Oculus session"); + ovr_Shutdown(); + } + + hmdDesc = ovr_GetHmdDesc(session); + + TraceLog(INFO, "OVR: Product Name: %s", hmdDesc.ProductName); + TraceLog(INFO, "OVR: Manufacturer: %s", hmdDesc.Manufacturer); + TraceLog(INFO, "OVR: Product ID: %i", hmdDesc.ProductId); + TraceLog(INFO, "OVR: Product Type: %i", hmdDesc.Type); + TraceLog(INFO, "OVR: Serian Number: %s", hmdDesc.SerialNumber); + TraceLog(INFO, "OVR: Resolution: %ix%i", hmdDesc.Resolution.w, hmdDesc.Resolution.h); + + screenWidth = hmdDesc.Resolution.w/2; + screenHeight = hmdDesc.Resolution.h/2; + + // Initialize Oculus Buffers + layer = InitOculusLayer(session); + buffer = LoadOculusBuffer(session, layer.width, layer.height); + mirror = LoadOculusMirror(session, hmdDesc.Resolution.w/2, hmdDesc.Resolution.h/2); + layer.eyeLayer.ColorTexture[0] = buffer.textureChain; //SetOculusLayerTexture(eyeLayer, buffer.textureChain); +} + +// Close Oculus Rift device +void CloseOculusDevice(void) +{ + UnloadOculusMirror(session, mirror); // Unload Oculus mirror buffer + UnloadOculusBuffer(session, buffer); // Unload Oculus texture buffers + + ovr_Destroy(session); // Must be called after glfwTerminate() --> REALLY??? + ovr_Shutdown(); +} + +// Update Oculus Rift tracking (position and orientation) +void UpdateOculusTracking(void) +{ + frameIndex++; + + ovrPosef eyePoses[2]; + ovr_GetEyePoses(session, frameIndex, ovrTrue, layer.viewScaleDesc.HmdToEyeOffset, eyePoses, &layer.eyeLayer.SensorSampleTime); + + layer.eyeLayer.RenderPose[0] = eyePoses[0]; + layer.eyeLayer.RenderPose[1] = eyePoses[1]; +} +#endif + // Detect if KEY_ESCAPE pressed or Close icon pressed bool WindowShouldClose(void) { diff --git a/src/raylib.h b/src/raylib.h index efd96a67..bdaaeb08 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -578,6 +578,12 @@ void InitWindow(int width, int height, struct android_app *state); // Init Andr void InitWindow(int width, int height, const char *title); // Initialize Window and OpenGL Graphics #endif +#if defined(PLATFORM_OCULUS) +void InitOculusDevice(void); // Init Oculus Rift device +void CloseOculusDevice(void); // Close Oculus Rift device +void UpdateOculusTracking(void); // Update Oculus Rift tracking (position and orientation) +#endif + void CloseWindow(void); // Close Window and Terminate Context bool WindowShouldClose(void); // Detect if KEY_ESCAPE pressed or Close icon pressed bool IsWindowMinimized(void); // Detect if window has been minimized (or lost focus) -- cgit v1.2.3 From 60232810d83c7ea3a52491f0b20444003be53358 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Fri, 3 Jun 2016 19:00:58 +0200 Subject: Added some comments --- src/raygui.c | 3 +-- src/raylib.h | 11 ++++++----- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src/raylib.h') diff --git a/src/raygui.c b/src/raygui.c index eaf15224..5064f123 100644 --- a/src/raygui.c +++ b/src/raygui.c @@ -177,7 +177,7 @@ static bool CheckCollisionPointRec(Vector2 point, Rectangle rec); // Check if p static const char *FormatText(const char *text, ...); // Formatting of text with variables to 'embed' // NOTE: raygui depend on some raylib input and drawing functions -// TODO: Set your own functions +// TODO: Replace by your own functions static Vector2 GetMousePosition() { return (Vector2){ 0.0f, 0.0f }; } static int IsMouseButtonDown(int button) { return 0; } static int IsMouseButtonPressed(int button) { return 0; } @@ -191,7 +191,6 @@ static int MeasureText(const char *text, int fontSize) { return 0; } static void DrawText(const char *text, int posX, int posY, int fontSize, Color color) { } static void DrawRectangleRec(Rectangle rec, Color color) { } static void DrawRectangle(int posX, int posY, int width, int height, Color color) { DrawRectangleRec((Rectangle){ posX, posY, width, height }, color); } - #endif //---------------------------------------------------------------------------------- diff --git a/src/raylib.h b/src/raylib.h index bdaaeb08..706c4f4a 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -64,6 +64,7 @@ //#define PLATFORM_ANDROID // Android device //#define PLATFORM_RPI // Raspberry Pi //#define PLATFORM_WEB // HTML5 (emscripten, asm.js) +//#define PLATFORM_OCULUS // Oculus Rift CV1 // Security check in case no PLATFORM_* defined #if !defined(PLATFORM_DESKTOP) && !defined(PLATFORM_ANDROID) && !defined(PLATFORM_RPI) && !defined(PLATFORM_WEB) @@ -71,7 +72,7 @@ #endif #if defined(PLATFORM_ANDROID) - typedef struct android_app; // Define android_app struct (android_native_app_glue.h) + typedef struct android_app; // Define android_app struct (android_native_app_glue.h) #endif //---------------------------------------------------------------------------------- @@ -448,14 +449,14 @@ typedef enum { LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT } LightType; // Ray type (useful for raycast) typedef struct Ray { - Vector3 position; - Vector3 direction; + Vector3 position; // Ray position (origin) + Vector3 direction; // Ray direction } Ray; // Sound source type typedef struct Sound { - unsigned int source; - unsigned int buffer; + unsigned int source; // Sound audio source id + unsigned int buffer; // Sound audio buffer id } Sound; // Wave type, defines audio wave data -- cgit v1.2.3