main.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. 
  2. /*
  3. TODO:
  4. * Create a visual graph with instruments, filters, speakers and file recorders to test a modular sound engine.
  5. * Allow recording the output of a session into a hi-fi stereo sound buffer, which can later be exported as a file.
  6. * Create a basic compressed music format for looping sounds in different speed and volume from compressed interpolated curves.
  7. * Make a list of named instruments containing a list of voices.
  8. Each voice refers to a sound buffer by index (using names in files) and an envelope for how to play the sound.
  9. Each voice will be played as its own instrument but from the same input for a richer sound without having to duplicate notes.
  10. The sounds can be either embedded into the project (editable for tiny instrument patterns) or refer to external files (for whole music tracks).
  11. * Store, modify, import and export MIDI tracks.
  12. */
  13. #include "../../DFPSR/includeFramework.h"
  14. #include "../SoundEngine/soundEngine.h"
  15. using namespace dsr;
  16. // Global
  17. bool running = true;
  18. Window window;
  19. static const double pi = 3.1415926535897932384626433832795;
  20. static const double cyclesToRadians = pi * 2.0;
  21. static const int toneCount = 10;
  22. Array<int> basicTone = Array<int>(toneCount, -1);
  23. int testSound;
  24. Array<int> playing = Array<int>(toneCount, -1);
  25. int createSine(int frequency, const ReadableString &name) {
  26. return soundEngine_insertSoundBuffer(sound_generate_function(44100 / frequency, 1, 44100, [frequency](double time, uint32_t channelIndex) {
  27. return sin(time * (cyclesToRadians * double(frequency))) * 0.25f;
  28. }), name, false);
  29. }
  30. void createTestProject() {
  31. // Loaded from file
  32. testSound = soundEngine_loadSoundFromFile(U"Water.wav");
  33. // Pure tones
  34. for (int t = 0; t < toneCount; t++) {
  35. playing[t] = -1;
  36. }
  37. basicTone[0] = createSine(261, U"C 4"); // C 4
  38. basicTone[1] = createSine(293, U"D 4"); // D 4
  39. basicTone[2] = createSine(329, U"E 4"); // E 4
  40. basicTone[3] = createSine(349, U"F 4"); // F 4
  41. basicTone[4] = createSine(392, U"G 4"); // G 4
  42. basicTone[5] = createSine(440, U"A 4"); // A 4
  43. basicTone[6] = createSine(493, U"B 4"); // B 4
  44. basicTone[7] = createSine(523, U"C 5"); // C 5
  45. basicTone[8] = createSine(587, U"D 5"); // D 5
  46. basicTone[9] = createSine(659, U"E 5"); // E 5
  47. }
  48. static EnvelopeSettings envelope = EnvelopeSettings(0.1, 0.2, 0.8, 0.4, 0.1, -0.02, 0.04, 0.5);
  49. static double previewPressTime = 1.0;
  50. static double previewViewTime = 4.0;
  51. static int selectedBuffer = 0;
  52. static void limitSelection() {
  53. int maxIndex = soundEngine_getSoundBufferCount() - 1;
  54. if (selectedBuffer < 0) selectedBuffer = 0;
  55. if (selectedBuffer > maxIndex) selectedBuffer = maxIndex;
  56. }
  57. DSR_MAIN_CALLER(dsrMain)
  58. void dsrMain(List<String> args) {
  59. // Start sound thread
  60. printText("Initializing sound\n");
  61. soundEngine_initialize();
  62. // Create something to test
  63. printText("Creating test project\n");
  64. createTestProject();
  65. // Create a window
  66. window = window_create(U"Sound generator", 800, 600);
  67. // Bind methods to events
  68. window_setKeyboardEvent(window, [](const KeyboardEvent& event) {
  69. DsrKey key = event.dsrKey;
  70. if (event.keyboardEventType == KeyboardEventType::KeyDown) {
  71. if (key == DsrKey_Escape) {
  72. running = false;
  73. } else if (key >= DsrKey_1 && key <= DsrKey_9) {
  74. int toneIndex = key - DsrKey_1;
  75. // TODO: Stop or reactivate sounds that are still fading out with the same tone to reduce the number of sound players running at the same time.
  76. playing[toneIndex] = soundEngine_playSound(basicTone[toneIndex], true, 1.0f, 1.0f, envelope);
  77. } else if (key == DsrKey_0) {
  78. playing[9] = soundEngine_playSound(basicTone[9], true, 1.0f, 1.0f, envelope);
  79. } else if (key == DsrKey_Return) {
  80. // TODO: Loop while holding return and then turn off looping on release.
  81. soundEngine_playSound(selectedBuffer, false);
  82. } else if (key == DsrKey_A) {
  83. // Play from left side.
  84. soundEngine_playSound(testSound, false, 1.0f, 0.0f);
  85. } else if (key == DsrKey_S) {
  86. // Play with half effect.
  87. soundEngine_playSound(testSound, false, 0.5f, 0.5f);
  88. } else if (key == DsrKey_D) {
  89. // Play from right side.
  90. soundEngine_playSound(testSound, false, 0.0f, 1.0f);
  91. } else if (key == DsrKey_UpArrow) {
  92. selectedBuffer--;
  93. limitSelection();
  94. } else if (key == DsrKey_DownArrow) {
  95. selectedBuffer++;
  96. limitSelection();
  97. }
  98. } else if (event.keyboardEventType == KeyboardEventType::KeyUp) {
  99. if (key >= DsrKey_1 && key <= DsrKey_9) {
  100. int toneIndex = key - DsrKey_1;
  101. soundEngine_releaseSound(playing[toneIndex]);
  102. } else if (key == DsrKey_0) {
  103. soundEngine_releaseSound(playing[9]);
  104. } else if (key == DsrKey_Space) {
  105. soundEngine_stopAllSounds();
  106. }
  107. }
  108. });
  109. /*
  110. component_setMouseDownEvent(mainPanel, [](const MouseEvent& event) {
  111. });
  112. component_setMouseMoveEvent(mainPanel, [](const MouseEvent& event) {
  113. });
  114. component_setMouseUpEvent(mainPanel, [](const MouseEvent& event) {
  115. });
  116. */
  117. window_setCloseEvent(window, []() {
  118. running = false;
  119. });
  120. // Execute
  121. while(running) {
  122. // Run the application in a delayed loop.
  123. time_sleepSeconds(0.01);
  124. window_executeEvents(window);
  125. // Fill the background
  126. AlignedImageRgbaU8 canvas = window_getCanvas(window);
  127. image_fill(canvas, ColorRgbaI32(64, 64, 64, 255));
  128. int width = image_getWidth(canvas);
  129. // Draw things
  130. int height = 50;
  131. int top = 0;
  132. soundEngine_drawEnvelope(canvas, IRect(0, 0, width, height), envelope, previewPressTime, previewViewTime);
  133. top += height;
  134. for (int s = 0; s < soundEngine_getSoundBufferCount(); s++) {
  135. soundEngine_drawSound(canvas, IRect(0, top, width, height), s, s == selectedBuffer);
  136. top += height;
  137. }
  138. // Draw interface
  139. window_drawComponents(window);
  140. // Show the final image
  141. window_showCanvas(window);
  142. }
  143. // Close sound thread
  144. printText("Terminating sound\n");
  145. soundEngine_terminate();
  146. }