audio_music_stream.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. /*******************************************************************************************
  2. *
  3. * raylib [audio] example - Music playing (streaming)
  4. *
  5. * Example originally created with raylib 1.3, last time updated with raylib 4.2
  6. *
  7. * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
  8. * BSD-like license that allows static linking with closed source software
  9. *
  10. * Copyright (c) 2015-2022 Ramon Santamaria (@raysan5)
  11. *
  12. ********************************************************************************************/
  13. #include "raylib.h"
  14. #include <stdlib.h> // Required for: NULL
  15. // Audio effect: lowpass filter
  16. static void AudioProcessEffectLPF(void *buffer, unsigned int frames)
  17. {
  18. static float low[2] = { 0.0f, 0.0f };
  19. static const float cutoff = 70.0f / 44100.0f; // 70 Hz lowpass filter
  20. const float k = cutoff / (cutoff + 0.1591549431f); // RC filter formula
  21. for (unsigned int i = 0; i < frames*2; i += 2)
  22. {
  23. float l = ((float *)buffer)[i], r = ((float *)buffer)[i + 1];
  24. low[0] += k * (l - low[0]);
  25. low[1] += k * (r - low[1]);
  26. ((float *)buffer)[i] = low[0];
  27. ((float *)buffer)[i + 1] = low[1];
  28. }
  29. }
  30. static float *delayBuffer = NULL;
  31. static unsigned int delayBufferSize = 0;
  32. static unsigned int delayReadIndex = 2;
  33. static unsigned int delayWriteIndex = 0;
  34. // Audio effect: delay
  35. static void AudioProcessEffectDelay(void *buffer, unsigned int frames)
  36. {
  37. for (unsigned int i = 0; i < frames*2; i += 2)
  38. {
  39. float leftDelay = delayBuffer[delayReadIndex++]; // ERROR: Reading buffer -> WHY??? Maybe thread related???
  40. float rightDelay = delayBuffer[delayReadIndex++];
  41. if (delayReadIndex == delayBufferSize) delayReadIndex = 0;
  42. ((float *)buffer)[i] = 0.5f*((float *)buffer)[i] + 0.5f*leftDelay;
  43. ((float *)buffer)[i + 1] = 0.5f*((float *)buffer)[i + 1] + 0.5f*rightDelay;
  44. delayBuffer[delayWriteIndex++] = ((float *)buffer)[i];
  45. delayBuffer[delayWriteIndex++] = ((float *)buffer)[i + 1];
  46. if (delayWriteIndex == delayBufferSize) delayWriteIndex = 0;
  47. }
  48. }
  49. //------------------------------------------------------------------------------------
  50. // Program main entry point
  51. //------------------------------------------------------------------------------------
  52. int main(void)
  53. {
  54. // Initialization
  55. //--------------------------------------------------------------------------------------
  56. const int screenWidth = 800;
  57. const int screenHeight = 450;
  58. InitWindow(screenWidth, screenHeight, "raylib [audio] example - music playing (streaming)");
  59. InitAudioDevice(); // Initialize audio device
  60. Music music = LoadMusicStream("resources/country.mp3");
  61. // Allocate buffer for the delay effect
  62. delayBufferSize = 48000 * 2;
  63. delayBuffer = (float *)RL_CALLOC(delayBufferSize, sizeof(float)); // 1 second delay (device sampleRate*channels)
  64. PlayMusicStream(music);
  65. float timePlayed = 0.0f;
  66. bool pause = false;
  67. bool hasFilter = true;
  68. bool hasDelay = true;
  69. SetTargetFPS(60); // Set our game to run at 60 frames-per-second
  70. //--------------------------------------------------------------------------------------
  71. // Main game loop
  72. while (!WindowShouldClose()) // Detect window close button or ESC key
  73. {
  74. // Update
  75. //----------------------------------------------------------------------------------
  76. UpdateMusicStream(music); // Update music buffer with new stream data
  77. // Restart music playing (stop and play)
  78. if (IsKeyPressed(KEY_SPACE))
  79. {
  80. StopMusicStream(music);
  81. PlayMusicStream(music);
  82. }
  83. // Pause/Resume music playing
  84. if (IsKeyPressed(KEY_P))
  85. {
  86. pause = !pause;
  87. if (pause) PauseMusicStream(music);
  88. else ResumeMusicStream(music);
  89. }
  90. // Add/Remove effect: lowpass filter
  91. if (IsKeyPressed(KEY_F))
  92. {
  93. hasFilter = !hasFilter;
  94. if (hasFilter) AttachAudioStreamProcessor(music.stream, AudioProcessEffectLPF);
  95. else DetachAudioStreamProcessor(music.stream, AudioProcessEffectLPF);
  96. }
  97. // Add/Remove effect: delay
  98. if (IsKeyPressed(KEY_D))
  99. {
  100. hasDelay = !hasDelay;
  101. if (hasDelay) AttachAudioStreamProcessor(music.stream, AudioProcessEffectDelay);
  102. else DetachAudioStreamProcessor(music.stream, AudioProcessEffectDelay);
  103. }
  104. // Get timePlayed scaled to bar dimensions (400 pixels)
  105. timePlayed = GetMusicTimePlayed(music)/GetMusicTimeLength(music)*400;
  106. if (timePlayed > 400) StopMusicStream(music);
  107. //----------------------------------------------------------------------------------
  108. // Draw
  109. //----------------------------------------------------------------------------------
  110. BeginDrawing();
  111. ClearBackground(RAYWHITE);
  112. DrawText("MUSIC SHOULD BE PLAYING!", 255, 150, 20, LIGHTGRAY);
  113. DrawRectangle(200, 200, 400, 12, LIGHTGRAY);
  114. DrawRectangle(200, 200, (int)timePlayed, 12, MAROON);
  115. DrawRectangleLines(200, 200, 400, 12, GRAY);
  116. DrawText("PRESS SPACE TO RESTART MUSIC", 215, 250, 20, LIGHTGRAY);
  117. DrawText("PRESS P TO PAUSE/RESUME MUSIC", 208, 280, 20, LIGHTGRAY);
  118. EndDrawing();
  119. //----------------------------------------------------------------------------------
  120. }
  121. // De-Initialization
  122. //--------------------------------------------------------------------------------------
  123. UnloadMusicStream(music); // Unload music stream buffers from RAM
  124. CloseAudioDevice(); // Close audio device (music streaming is automatically stopped)
  125. RL_FREE(delayBuffer); // Free delay buffer
  126. CloseWindow(); // Close window and OpenGL context
  127. //--------------------------------------------------------------------------------------
  128. return 0;
  129. }