ModSampleCopy.h 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /*
  2. * ModSampleCopy.h
  3. * ---------------
  4. * Purpose: Functions for copying ModSample data.
  5. * Notes : (currently none)
  6. * Authors: OpenMPT Devs
  7. * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
  8. */
  9. #pragma once
  10. #include "openmpt/all/BuildSettings.hpp"
  11. #include "openmpt/soundbase/SampleDecode.hpp"
  12. OPENMPT_NAMESPACE_BEGIN
  13. struct ModSample;
  14. // Copy a mono sample data buffer.
  15. template <typename SampleConversion, typename Tbyte>
  16. size_t CopyMonoSample(ModSample &sample, const Tbyte *sourceBuffer, size_t sourceSize, SampleConversion conv = SampleConversion())
  17. {
  18. MPT_ASSERT(sample.GetNumChannels() == 1);
  19. MPT_ASSERT(sample.GetElementarySampleSize() == sizeof(typename SampleConversion::output_t));
  20. const size_t frameSize = SampleConversion::input_inc;
  21. const size_t countFrames = std::min(sourceSize / frameSize, static_cast<std::size_t>(sample.nLength));
  22. size_t numFrames = countFrames;
  23. SampleConversion sampleConv(conv);
  24. const std::byte * MPT_RESTRICT inBuf = mpt::byte_cast<const std::byte*>(sourceBuffer);
  25. typename SampleConversion::output_t * MPT_RESTRICT outBuf = static_cast<typename SampleConversion::output_t *>(sample.samplev());
  26. while(numFrames--)
  27. {
  28. *outBuf = sampleConv(inBuf);
  29. inBuf += SampleConversion::input_inc;
  30. outBuf++;
  31. }
  32. return frameSize * countFrames;
  33. }
  34. // Copy a stereo interleaved sample data buffer.
  35. template <typename SampleConversion, typename Tbyte>
  36. size_t CopyStereoInterleavedSample(ModSample &sample, const Tbyte *sourceBuffer, size_t sourceSize, SampleConversion conv = SampleConversion())
  37. {
  38. MPT_ASSERT(sample.GetNumChannels() == 2);
  39. MPT_ASSERT(sample.GetElementarySampleSize() == sizeof(typename SampleConversion::output_t));
  40. const size_t frameSize = 2 * SampleConversion::input_inc;
  41. const size_t countFrames = std::min(sourceSize / frameSize, static_cast<std::size_t>(sample.nLength));
  42. size_t numFrames = countFrames;
  43. SampleConversion sampleConvLeft(conv);
  44. SampleConversion sampleConvRight(conv);
  45. const std::byte * MPT_RESTRICT inBuf = mpt::byte_cast<const std::byte*>(sourceBuffer);
  46. typename SampleConversion::output_t * MPT_RESTRICT outBuf = static_cast<typename SampleConversion::output_t *>(sample.samplev());
  47. while(numFrames--)
  48. {
  49. *outBuf = sampleConvLeft(inBuf);
  50. inBuf += SampleConversion::input_inc;
  51. outBuf++;
  52. *outBuf = sampleConvRight(inBuf);
  53. inBuf += SampleConversion::input_inc;
  54. outBuf++;
  55. }
  56. return frameSize * countFrames;
  57. }
  58. // Copy a stereo split sample data buffer.
  59. template <typename SampleConversion, typename Tbyte>
  60. size_t CopyStereoSplitSample(ModSample &sample, const Tbyte *sourceBuffer, size_t sourceSize, SampleConversion conv = SampleConversion())
  61. {
  62. MPT_ASSERT(sample.GetNumChannels() == 2);
  63. MPT_ASSERT(sample.GetElementarySampleSize() == sizeof(typename SampleConversion::output_t));
  64. const size_t sampleSize = SampleConversion::input_inc;
  65. const size_t sourceSizeLeft = std::min(static_cast<std::size_t>(sample.nLength) * SampleConversion::input_inc, sourceSize);
  66. const size_t sourceSizeRight = std::min(static_cast<std::size_t>(sample.nLength) * SampleConversion::input_inc, sourceSize - sourceSizeLeft);
  67. const size_t countSamplesLeft = sourceSizeLeft / sampleSize;
  68. const size_t countSamplesRight = sourceSizeRight / sampleSize;
  69. size_t numSamplesLeft = countSamplesLeft;
  70. SampleConversion sampleConvLeft(conv);
  71. const std::byte * MPT_RESTRICT inBufLeft = mpt::byte_cast<const std::byte*>(sourceBuffer);
  72. typename SampleConversion::output_t * MPT_RESTRICT outBufLeft = static_cast<typename SampleConversion::output_t *>(sample.samplev());
  73. while(numSamplesLeft--)
  74. {
  75. *outBufLeft = sampleConvLeft(inBufLeft);
  76. inBufLeft += SampleConversion::input_inc;
  77. outBufLeft += 2;
  78. }
  79. size_t numSamplesRight = countSamplesRight;
  80. SampleConversion sampleConvRight(conv);
  81. const std::byte * MPT_RESTRICT inBufRight = mpt::byte_cast<const std::byte*>(sourceBuffer) + sample.nLength * SampleConversion::input_inc;
  82. typename SampleConversion::output_t * MPT_RESTRICT outBufRight = static_cast<typename SampleConversion::output_t *>(sample.samplev()) + 1;
  83. while(numSamplesRight--)
  84. {
  85. *outBufRight = sampleConvRight(inBufRight);
  86. inBufRight += SampleConversion::input_inc;
  87. outBufRight += 2;
  88. }
  89. return (countSamplesLeft + countSamplesRight) * sampleSize;
  90. }
  91. // Copy a sample data buffer and normalize it. Requires slightly advanced sample conversion functor.
  92. template <typename SampleConversion, typename Tbyte>
  93. size_t CopyAndNormalizeSample(ModSample &sample, const Tbyte *sourceBuffer, size_t sourceSize, typename SampleConversion::peak_t *srcPeak = nullptr, SampleConversion conv = SampleConversion())
  94. {
  95. const size_t sampleSize = SampleConversion::input_inc;
  96. MPT_ASSERT(sample.GetElementarySampleSize() == sizeof(typename SampleConversion::output_t));
  97. size_t numSamples = sample.nLength * sample.GetNumChannels();
  98. LimitMax(numSamples, sourceSize / sampleSize);
  99. const std::byte * inBuf = mpt::byte_cast<const std::byte*>(sourceBuffer);
  100. // Finding max value
  101. SampleConversion sampleConv(conv);
  102. for(size_t i = numSamples; i != 0; i--)
  103. {
  104. sampleConv.FindMax(inBuf);
  105. inBuf += SampleConversion::input_inc;
  106. }
  107. // If buffer is silent (maximum is 0), don't bother normalizing the sample - just keep the already silent buffer.
  108. if(!sampleConv.IsSilent())
  109. {
  110. inBuf = sourceBuffer;
  111. // Copying buffer.
  112. typename SampleConversion::output_t *outBuf = static_cast<typename SampleConversion::output_t *>(sample.samplev());
  113. for(size_t i = numSamples; i != 0; i--)
  114. {
  115. *outBuf = sampleConv(inBuf);
  116. outBuf++;
  117. inBuf += SampleConversion::input_inc;
  118. }
  119. }
  120. if(srcPeak)
  121. {
  122. *srcPeak = sampleConv.GetSrcPeak();
  123. }
  124. return numSamples * sampleSize;
  125. }
  126. OPENMPT_NAMESPACE_END