Audio plugin host https://kx.studio/carla
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.

111 lines
3.1KB

  1. /* Copyright 2016, Ableton AG, Berlin. All rights reserved.
  2. *
  3. * This program is free software: you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation, either version 2 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. *
  16. * If you would like to incorporate Link into a proprietary software application,
  17. * please contact <link-devs@ableton.com>.
  18. */
  19. #include "AudioEngine.hpp"
  20. // Make sure to define this before <cmath> is included for Windows
  21. #define _USE_MATH_DEFINES
  22. #include <cmath>
  23. namespace ableton
  24. {
  25. namespace link
  26. {
  27. AudioEngine::AudioEngine(Link& link)
  28. : mLink(link)
  29. , mSharedEngineData({0., false, 4.})
  30. {
  31. }
  32. double AudioEngine::beatTime() const
  33. {
  34. const auto timeline = mLink.captureAppTimeline();
  35. return timeline.beatAtTime(mLink.clock().micros(), mSharedEngineData.quantum);
  36. }
  37. void AudioEngine::setTempo(double tempo)
  38. {
  39. const std::lock_guard<std::mutex> lock(mEngineDataGuard);
  40. mSharedEngineData.requestedTempo = tempo;
  41. }
  42. double AudioEngine::quantum() const
  43. {
  44. return mSharedEngineData.quantum;
  45. }
  46. void AudioEngine::setQuantum(double quantum)
  47. {
  48. const std::lock_guard<std::mutex> lock(mEngineDataGuard);
  49. mSharedEngineData.quantum = quantum;
  50. mSharedEngineData.resetBeatTime = true;
  51. }
  52. AudioEngine::EngineData AudioEngine::pullEngineData()
  53. {
  54. auto engineData = EngineData{};
  55. if (mEngineDataGuard.try_lock())
  56. {
  57. engineData.requestedTempo = mSharedEngineData.requestedTempo;
  58. mSharedEngineData.requestedTempo = 0;
  59. engineData.resetBeatTime = mSharedEngineData.resetBeatTime;
  60. engineData.quantum = mSharedEngineData.quantum;
  61. mSharedEngineData.resetBeatTime = false;
  62. mEngineDataGuard.unlock();
  63. }
  64. return engineData;
  65. }
  66. void AudioEngine::timelineCallback(const std::chrono::microseconds hostTime, LinkTimeInfo* const info)
  67. {
  68. const auto engineData = pullEngineData();
  69. auto timeline = mLink.captureAudioTimeline();
  70. if (engineData.resetBeatTime)
  71. {
  72. // Reset the timeline so that beat 0 lands at the beginning of
  73. // this buffer and clear the flag.
  74. timeline.requestBeatAtTime(0, hostTime, engineData.quantum);
  75. }
  76. if (engineData.requestedTempo > 0)
  77. {
  78. // Set the newly requested tempo from the beginning of this buffer
  79. timeline.setTempo(engineData.requestedTempo, hostTime);
  80. }
  81. // Timeline modifications are complete, commit the results
  82. mLink.commitAudioTimeline(timeline);
  83. // Save timeline info
  84. info->beatsPerBar = engineData.quantum;
  85. info->beatsPerMinute = timeline.tempo();
  86. info->beat = timeline.beatAtTime(hostTime, engineData.quantum);
  87. info->phase = timeline.phaseAtTime(hostTime, engineData.quantum);
  88. }
  89. } // namespace link
  90. } // namespace ableton