You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

165 lines
6.1 KiB

  1. /*******************************************************************************************
  2. *
  3. * raylib [audio] example - Raw audio streaming
  4. *
  5. * This example has been created using raylib 1.6 (www.raylib.com)
  6. * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
  7. *
  8. * Example created by Ramon Santamaria (@raysan5) and reviewed by James Hofmann (@triplefox)
  9. *
  10. * Copyright (c) 2015-2019 Ramon Santamaria (@raysan5) and James Hofmann (@triplefox)
  11. *
  12. ********************************************************************************************/
  13. #include "raylib.h"
  14. #include <stdlib.h> // Required for: malloc(), free()
  15. #include <math.h> // Required for: sinf()
  16. #include <string.h> // Required for: memcpy()
  17. #define MAX_SAMPLES 512
  18. #define MAX_SAMPLES_PER_UPDATE 4096
  19. int main(void)
  20. {
  21. // Initialization
  22. //--------------------------------------------------------------------------------------
  23. const int screenWidth = 800;
  24. const int screenHeight = 450;
  25. InitWindow(screenWidth, screenHeight, "raylib [audio] example - raw audio streaming");
  26. InitAudioDevice(); // Initialize audio device
  27. // Init raw audio stream (sample rate: 22050, sample size: 16bit-short, channels: 1-mono)
  28. AudioStream stream = InitAudioStream(22050, 16, 1);
  29. // Buffer for the single cycle waveform we are synthesizing
  30. short *data = (short *)malloc(sizeof(short)*MAX_SAMPLES);
  31. // Frame buffer, describing the waveform when repeated over the course of a frame
  32. short *writeBuf = (short *)malloc(sizeof(short)*MAX_SAMPLES_PER_UPDATE);
  33. PlayAudioStream(stream); // Start processing stream buffer (no data loaded currently)
  34. // Position read in to determine next frequency
  35. Vector2 mousePosition = { -100.0f, -100.0f };
  36. // Cycles per second (hz)
  37. float frequency = 440.0f;
  38. // Previous value, used to test if sine needs to be rewritten, and to smoothly modulate frequency
  39. float oldFrequency = 1.0f;
  40. // Cursor to read and copy the samples of the sine wave buffer
  41. int readCursor = 0;
  42. // Computed size in samples of the sine wave
  43. int waveLength = 1;
  44. Vector2 position = { 0, 0 };
  45. SetTargetFPS(30); // Set our game to run at 30 frames-per-second
  46. //--------------------------------------------------------------------------------------
  47. // Main game loop
  48. while (!WindowShouldClose()) // Detect window close button or ESC key
  49. {
  50. // Update
  51. //----------------------------------------------------------------------------------
  52. // Sample mouse input.
  53. mousePosition = GetMousePosition();
  54. if (IsMouseButtonDown(MOUSE_LEFT_BUTTON))
  55. {
  56. float fp = (float)(mousePosition.y);
  57. frequency = 40.0f + (float)(fp);
  58. }
  59. // Rewrite the sine wave.
  60. // Compute two cycles to allow the buffer padding, simplifying any modulation, resampling, etc.
  61. if (frequency != oldFrequency)
  62. {
  63. // Compute wavelength. Limit size in both directions.
  64. int oldWavelength = waveLength;
  65. waveLength = (int)(22050/frequency);
  66. if (waveLength > MAX_SAMPLES/2) waveLength = MAX_SAMPLES/2;
  67. if (waveLength < 1) waveLength = 1;
  68. // Write sine wave.
  69. for (int i = 0; i < waveLength*2; i++)
  70. {
  71. data[i] = (short)(sinf(((2*PI*(float)i/waveLength)))*32000);
  72. }
  73. // Scale read cursor's position to minimize transition artifacts
  74. readCursor = (int)(readCursor * ((float)waveLength / (float)oldWavelength));
  75. oldFrequency = frequency;
  76. }
  77. // Refill audio stream if required
  78. if (IsAudioStreamProcessed(stream))
  79. {
  80. // Synthesize a buffer that is exactly the requested size
  81. int writeCursor = 0;
  82. while (writeCursor < MAX_SAMPLES_PER_UPDATE)
  83. {
  84. // Start by trying to write the whole chunk at once
  85. int writeLength = MAX_SAMPLES_PER_UPDATE-writeCursor;
  86. // Limit to the maximum readable size
  87. int readLength = waveLength-readCursor;
  88. if (writeLength > readLength) writeLength = readLength;
  89. // Write the slice
  90. memcpy(writeBuf + writeCursor, data + readCursor, writeLength*sizeof(short));
  91. // Update cursors and loop audio
  92. readCursor = (readCursor + writeLength) % waveLength;
  93. writeCursor += writeLength;
  94. }
  95. // Copy finished frame to audio stream
  96. UpdateAudioStream(stream, writeBuf, MAX_SAMPLES_PER_UPDATE);
  97. }
  98. //----------------------------------------------------------------------------------
  99. // Draw
  100. //----------------------------------------------------------------------------------
  101. BeginDrawing();
  102. ClearBackground(RAYWHITE);
  103. DrawText(FormatText("sine frequency: %i",(int)frequency), GetScreenWidth() - 220, 10, 20, RED);
  104. DrawText("click mouse button to change frequency", 10, 10, 20, DARKGRAY);
  105. // Draw the current buffer state proportionate to the screen
  106. for (int i = 0; i < screenWidth; i++)
  107. {
  108. position.x = i;
  109. position.y = 250 + 50*data[i*MAX_SAMPLES/screenWidth]/32000;
  110. DrawPixelV(position, RED);
  111. }
  112. EndDrawing();
  113. //----------------------------------------------------------------------------------
  114. }
  115. // De-Initialization
  116. //--------------------------------------------------------------------------------------
  117. free(data); // Unload sine wave data
  118. free(writeBuf); // Unload write buffer
  119. CloseAudioStream(stream); // Close raw audio stream and delete buffers from RAM
  120. CloseAudioDevice(); // Close audio device (music streaming is automatically stopped)
  121. CloseWindow(); // Close window and OpenGL context
  122. //--------------------------------------------------------------------------------------
  123. return 0;
  124. }