audio_raw_stream.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  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. SetAudioStreamBufferSizeDefault(MAX_SAMPLES_PER_UPDATE);
  28. // Init raw audio stream (sample rate: 22050, sample size: 16bit-short, channels: 1-mono)
  29. AudioStream stream = LoadAudioStream(44100, 16, 1);
  30. // Buffer for the single cycle waveform we are synthesizing
  31. short *data = (short *)malloc(sizeof(short)*MAX_SAMPLES);
  32. // Frame buffer, describing the waveform when repeated over the course of a frame
  33. short *writeBuf = (short *)malloc(sizeof(short)*MAX_SAMPLES_PER_UPDATE);
  34. PlayAudioStream(stream); // Start processing stream buffer (no data loaded currently)
  35. // Position read in to determine next frequency
  36. Vector2 mousePosition = { -100.0f, -100.0f };
  37. // Cycles per second (hz)
  38. float frequency = 440.0f;
  39. // Previous value, used to test if sine needs to be rewritten, and to smoothly modulate frequency
  40. float oldFrequency = 1.0f;
  41. // Cursor to read and copy the samples of the sine wave buffer
  42. int readCursor = 0;
  43. // Computed size in samples of the sine wave
  44. int waveLength = 1;
  45. Vector2 position = { 0, 0 };
  46. SetTargetFPS(30); // Set our game to run at 30 frames-per-second
  47. //--------------------------------------------------------------------------------------
  48. // Main game loop
  49. while (!WindowShouldClose()) // Detect window close button or ESC key
  50. {
  51. // Update
  52. //----------------------------------------------------------------------------------
  53. // Sample mouse input.
  54. mousePosition = GetMousePosition();
  55. if (IsMouseButtonDown(MOUSE_BUTTON_LEFT))
  56. {
  57. float fp = (float)(mousePosition.y);
  58. frequency = 40.0f + (float)(fp);
  59. }
  60. // Rewrite the sine wave.
  61. // Compute two cycles to allow the buffer padding, simplifying any modulation, resampling, etc.
  62. if (frequency != oldFrequency)
  63. {
  64. // Compute wavelength. Limit size in both directions.
  65. int oldWavelength = waveLength;
  66. waveLength = (int)(22050/frequency);
  67. if (waveLength > MAX_SAMPLES/2) waveLength = MAX_SAMPLES/2;
  68. if (waveLength < 1) waveLength = 1;
  69. // Write sine wave.
  70. for (int i = 0; i < waveLength*2; i++)
  71. {
  72. data[i] = (short)(sinf(((2*PI*(float)i/waveLength)))*32000);
  73. }
  74. // Scale read cursor's position to minimize transition artifacts
  75. readCursor = (int)(readCursor * ((float)waveLength / (float)oldWavelength));
  76. oldFrequency = frequency;
  77. }
  78. // Refill audio stream if required
  79. if (IsAudioStreamProcessed(stream))
  80. {
  81. // Synthesize a buffer that is exactly the requested size
  82. int writeCursor = 0;
  83. while (writeCursor < MAX_SAMPLES_PER_UPDATE)
  84. {
  85. // Start by trying to write the whole chunk at once
  86. int writeLength = MAX_SAMPLES_PER_UPDATE-writeCursor;
  87. // Limit to the maximum readable size
  88. int readLength = waveLength-readCursor;
  89. if (writeLength > readLength) writeLength = readLength;
  90. // Write the slice
  91. memcpy(writeBuf + writeCursor, data + readCursor, writeLength*sizeof(short));
  92. // Update cursors and loop audio
  93. readCursor = (readCursor + writeLength) % waveLength;
  94. writeCursor += writeLength;
  95. }
  96. // Copy finished frame to audio stream
  97. UpdateAudioStream(stream, writeBuf, MAX_SAMPLES_PER_UPDATE);
  98. }
  99. //----------------------------------------------------------------------------------
  100. // Draw
  101. //----------------------------------------------------------------------------------
  102. BeginDrawing();
  103. ClearBackground(RAYWHITE);
  104. DrawText(TextFormat("sine frequency: %i",(int)frequency), GetScreenWidth() - 220, 10, 20, RED);
  105. DrawText("click mouse button to change frequency", 10, 10, 20, DARKGRAY);
  106. // Draw the current buffer state proportionate to the screen
  107. for (int i = 0; i < screenWidth; i++)
  108. {
  109. position.x = (float)i;
  110. position.y = 250 + 50*data[i*MAX_SAMPLES/screenWidth]/32000.0f;
  111. DrawPixelV(position, RED);
  112. }
  113. EndDrawing();
  114. //----------------------------------------------------------------------------------
  115. }
  116. // De-Initialization
  117. //--------------------------------------------------------------------------------------
  118. free(data); // Unload sine wave data
  119. free(writeBuf); // Unload write buffer
  120. UnloadAudioStream(stream); // Close raw audio stream and delete buffers from RAM
  121. CloseAudioDevice(); // Close audio device (music streaming is automatically stopped)
  122. CloseWindow(); // Close window and OpenGL context
  123. //--------------------------------------------------------------------------------------
  124. return 0;
  125. }