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.

181 lines
4.0KB

  1. /*************************************************************************************
  2. * Original code copyright (C) 2012 Steve Folta
  3. * Converted to Juce module (C) 2016 Leo Olivers
  4. * Forked from https://github.com/stevefolta/SFZero
  5. * For license info please see the LICENSE file distributed with this source code
  6. *************************************************************************************/
  7. #include "SFZSound.h"
  8. #include "SFZReader.h"
  9. #include "SFZRegion.h"
  10. #include "SFZSample.h"
  11. namespace sfzero
  12. {
  13. Sound::Sound(const water::File &fileIn) : file_(fileIn) {}
  14. Sound::~Sound()
  15. {
  16. int numRegions = regions_.size();
  17. for (int i = 0; i < numRegions; ++i)
  18. {
  19. delete regions_[i];
  20. regions_.set(i, nullptr);
  21. }
  22. for (water::HashMap<water::String, Sample *>::Iterator i(samples_); i.next();)
  23. {
  24. delete i.getValue();
  25. }
  26. }
  27. bool Sound::appliesToNote(int /*midiNoteNumber*/)
  28. {
  29. // Just say yes; we can't truly know unless we're told the velocity as well.
  30. return true;
  31. }
  32. bool Sound::appliesToChannel(int /*midiChannel*/) { return true; }
  33. void Sound::addRegion(Region *region) { regions_.add(region); }
  34. Sample *Sound::addSample(water::String path, water::String defaultPath)
  35. {
  36. path = path.replaceCharacter('\\', '/');
  37. defaultPath = defaultPath.replaceCharacter('\\', '/');
  38. water::File sampleFile;
  39. if (defaultPath.isEmpty())
  40. {
  41. sampleFile = file_.getSiblingFile(path);
  42. }
  43. else
  44. {
  45. water::File defaultDir = file_.getSiblingFile(defaultPath);
  46. sampleFile = defaultDir.getChildFile(path);
  47. }
  48. water::String samplePath = sampleFile.getFullPathName();
  49. Sample *sample = samples_[samplePath];
  50. if (sample == nullptr)
  51. {
  52. sample = new Sample(sampleFile);
  53. samples_.set(samplePath, sample);
  54. }
  55. return sample;
  56. }
  57. void Sound::addError(const water::String &message) { errors_.add(message); }
  58. void Sound::addUnsupportedOpcode(const water::String &opcode)
  59. {
  60. if (!unsupportedOpcodes_.contains(opcode))
  61. {
  62. unsupportedOpcodes_.set(opcode, opcode);
  63. water::String warning = "unsupported opcode: ";
  64. warning << opcode;
  65. warnings_.add(warning);
  66. }
  67. }
  68. void Sound::loadRegions()
  69. {
  70. Reader reader(this);
  71. reader.read(file_);
  72. }
  73. void Sound::loadSamples(const LoadingIdleCallback& cb)
  74. {
  75. for (water::HashMap<water::String, Sample *>::Iterator i(samples_); i.next();)
  76. {
  77. Sample* const sample = i.getValue();
  78. if (sample->load())
  79. {
  80. carla_debug("Loaded sample '%s'", sample->getShortName().toRawUTF8());
  81. cb.callback(cb.callbackPtr);
  82. }
  83. else
  84. {
  85. addError("Couldn't load sample \"" + sample->getShortName() + "\"");
  86. }
  87. }
  88. }
  89. Region *Sound::getRegionFor(int note, int velocity, Region::Trigger trigger)
  90. {
  91. int numRegions = regions_.size();
  92. for (int i = 0; i < numRegions; ++i)
  93. {
  94. Region *region = regions_[i];
  95. if (region->matches(note, velocity, trigger))
  96. {
  97. return region;
  98. }
  99. }
  100. return nullptr;
  101. }
  102. int Sound::getNumRegions() { return regions_.size(); }
  103. Region *Sound::regionAt(int index) { return regions_[index]; }
  104. water::String Sound::dump()
  105. {
  106. water::String info;
  107. const water::StringArray& errors = getErrors();
  108. if (errors.size() > 0)
  109. {
  110. info << errors.size() << " errors: \n";
  111. info << errors.joinIntoString("\n");
  112. info << "\n";
  113. }
  114. else
  115. {
  116. info << "no errors.\n\n";
  117. }
  118. const water::StringArray& warnings = getWarnings();
  119. if (warnings.size() > 0)
  120. {
  121. info << warnings.size() << " warnings: \n";
  122. info << warnings.joinIntoString("\n");
  123. }
  124. else
  125. {
  126. info << "no warnings.\n";
  127. }
  128. #ifdef DEBUG
  129. if (regions_.size() > 0)
  130. {
  131. info << regions_.size() << " regions: \n";
  132. for (int i = 0; i < regions_.size(); ++i)
  133. {
  134. info << regions_[i]->dump();
  135. }
  136. }
  137. else
  138. {
  139. info << "no regions.\n";
  140. }
  141. if (samples_.size() > 0)
  142. {
  143. info << samples_.size() << " samples: \n";
  144. for (water::HashMap<water::String, Sample *>::Iterator i(samples_); i.next();)
  145. {
  146. info << i.getValue()->dump();
  147. }
  148. }
  149. else
  150. {
  151. info << "no samples.\n";
  152. }
  153. #endif
  154. return info;
  155. }
  156. }