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.

167 lines
4.5KB

  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 "SFZSample.h"
  8. #include "SFZDebug.h"
  9. #if 0
  10. #include "water/audioformat/AudioFormatManager.h"
  11. #include "water/audioformat/AudioFormatReader.h"
  12. #include "water/text/StringPairArray.h"
  13. #else
  14. extern "C" {
  15. #include "audio_decoder/ad.h"
  16. }
  17. #endif
  18. namespace sfzero
  19. {
  20. bool Sample::load()
  21. {
  22. #if 0
  23. static water::AudioFormatManager afm;
  24. static bool needsInit = true;
  25. if (needsInit)
  26. {
  27. needsInit = false;
  28. afm.registerBasicFormats();
  29. }
  30. water::AudioFormatReader* reader = afm.createReaderFor(file_);
  31. CARLA_SAFE_ASSERT_RETURN(reader != nullptr, false);
  32. sampleRate_ = reader->sampleRate;
  33. sampleLength_ = (water::uint64) reader->lengthInSamples;
  34. // Read some extra samples, which will be filled with zeros, so interpolation
  35. // can be done without having to check for the edge all the time.
  36. CARLA_SAFE_ASSERT_RETURN(sampleLength_ < std::numeric_limits<int>::max(), false);
  37. water::AudioSampleBuffer* buf = new water::AudioSampleBuffer((int) reader->numChannels, static_cast<int>(sampleLength_ + 4), true);
  38. reader->read(buf, 0, static_cast<int>(sampleLength_ + 4), 0, true, true);
  39. buffer_ = buf;
  40. water::StringPairArray *metadata = &reader->metadataValues;
  41. int numLoops = metadata->getValue("NumSampleLoops", "0").getIntValue();
  42. if (numLoops > 0)
  43. {
  44. loopStart_ = (water::uint64) metadata->getValue("Loop0Start", "0").getLargeIntValue();
  45. loopEnd_ = (water::uint64) metadata->getValue("Loop0End", "0").getLargeIntValue();
  46. }
  47. delete reader;
  48. #else
  49. const water::String filename(file_.getFullPathName());
  50. struct adinfo info;
  51. carla_zeroStruct(info);
  52. void* const handle = ad_open(filename.toRawUTF8(), &info);
  53. CARLA_SAFE_ASSERT_RETURN(handle != nullptr, false);
  54. if (info.frames >= std::numeric_limits<int>::max())
  55. {
  56. carla_stderr2("sfzero::Sample::load() - file is too big!");
  57. ad_close(handle);
  58. return false;
  59. }
  60. sampleRate_ = info.sample_rate;
  61. sampleLength_ = info.frames/info.channels;
  62. // TODO loopStart_, loopEnd_
  63. // read interleaved buffer
  64. float* const rbuffer = (float*)std::calloc(1, sizeof(float)*info.frames);
  65. if (rbuffer == nullptr)
  66. {
  67. carla_stderr2("sfzero::Sample::load() - out of memory");
  68. ad_close(handle);
  69. return false;
  70. }
  71. // Fix for misinformation using libsndfile
  72. if (info.frames % info.channels)
  73. --info.frames;
  74. const ssize_t r = ad_read(handle, rbuffer, info.frames);
  75. if (r != info.frames)
  76. {
  77. if (r != 0)
  78. carla_stderr2("sfzero::Sample::load() - failed to read complete file: " P_SSIZE " vs " P_INT64, r, info.frames);
  79. ad_close(handle);
  80. return false;
  81. }
  82. // NOTE: We add some extra samples, which will be filled with zeros,
  83. // so interpolation can be done without having to check for the edge all the time.
  84. buffer_ = new water::AudioSampleBuffer(info.channels, sampleLength_ + 4, true);
  85. for (int i=info.channels; --i >= 0;)
  86. buffer_->copyFromInterleavedSource(i, rbuffer, r);
  87. std::free(rbuffer);
  88. ad_close(handle);
  89. #endif
  90. return true;
  91. }
  92. Sample::~Sample() { }
  93. water::String Sample::getShortName() { return (file_.getFileName()); }
  94. void Sample::setBuffer(water::AudioSampleBuffer *newBuffer)
  95. {
  96. buffer_ = newBuffer;
  97. sampleLength_ = buffer_->getNumSamples();
  98. }
  99. water::AudioSampleBuffer *Sample::detachBuffer()
  100. {
  101. return buffer_.release();
  102. }
  103. water::String Sample::dump() { return file_.getFullPathName() + "\n"; }
  104. #ifdef DEBUG
  105. void Sample::checkIfZeroed(const char *where)
  106. {
  107. if (buffer_ == nullptr)
  108. {
  109. dbgprintf("SFZSample::checkIfZeroed(%s): no buffer!", where);
  110. return;
  111. }
  112. int samplesLeft = buffer_->getNumSamples();
  113. water::int64 nonzero = 0, zero = 0;
  114. const float *p = buffer_->getReadPointer(0);
  115. for (; samplesLeft > 0; --samplesLeft)
  116. {
  117. if (*p++ == 0.0)
  118. {
  119. zero += 1;
  120. }
  121. else
  122. {
  123. nonzero += 1;
  124. }
  125. }
  126. if (nonzero > 0)
  127. {
  128. dbgprintf("Buffer not zeroed at %s (%lu vs. %lu).", where, nonzero, zero);
  129. }
  130. else
  131. {
  132. dbgprintf("Buffer zeroed at %s! (%lu zeros)", where, zero);
  133. }
  134. }
  135. #endif // DEBUG
  136. }