SoundPlayer.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. 
  2. #include "SoundPlayer.h"
  3. namespace dsr {
  4. SoundPlayer::SoundPlayer(const SoundBuffer &soundBuffer, int32_t soundIndex, int64_t playerID, bool repeat, uint32_t startLocation, float leftVolume, float rightVolume, const EnvelopeSettings &envelopeSettings)
  5. : soundBuffer(soundBuffer),
  6. soundIndex(soundIndex),
  7. playerID(playerID),
  8. repeat(repeat),
  9. location(startLocation % sound_getSamplesPerChannel(soundBuffer)),
  10. fadeLeft(leftVolume < 0.9999f || leftVolume > 1.0001f),
  11. fadeRight(rightVolume < 0.9999f || rightVolume > 1.0001f),
  12. leftVolume(leftVolume),
  13. rightVolume(rightVolume),
  14. envelope(envelopeSettings) {}
  15. void player_getNextSamples(SoundPlayer &player, SafePointer<float> target, int32_t playedSamplesPerChannel, double secondsPerSample) {
  16. uint32_t totalSamplesPerChannel = sound_getSamplesPerChannel(player.soundBuffer);
  17. uint32_t channelCount = sound_getChannelCount(player.soundBuffer);
  18. SafePointer<const float> source = sound_getSafePointer(player.soundBuffer);
  19. uint32_t startIndex = player.location;
  20. uint32_t blockBytes = channelCount * sizeof(float);
  21. if (startIndex + playedSamplesPerChannel > totalSamplesPerChannel) {
  22. // TODO: Properly test this part of the code using regression tests.
  23. SafePointer<float> writer = target;
  24. // Calculate how many samples that are inside of the buffer.
  25. uint32_t insideSamples = totalSamplesPerChannel - startIndex;
  26. if (insideSamples > 0) {
  27. uintptr_t insideBytes = insideSamples * blockBytes;
  28. safeMemoryCopy(writer, source + (player.location * channelCount), insideBytes);
  29. writer.increaseBytes(insideBytes);
  30. }
  31. // Calculate how many samples that are outside of the buffer.
  32. uint32_t outsideSamples = playedSamplesPerChannel - insideSamples;
  33. if (player.repeat) {
  34. // Copy whole laps of the sound buffer.
  35. uintptr_t wholeLapBytes = totalSamplesPerChannel * blockBytes;
  36. while (outsideSamples >= totalSamplesPerChannel) {
  37. safeMemoryCopy(writer, source, wholeLapBytes);
  38. writer.increaseBytes(wholeLapBytes);
  39. outsideSamples -= totalSamplesPerChannel;
  40. }
  41. // Copy a partial lap at the end if there are samples remaining.
  42. if (outsideSamples > 0) {
  43. uintptr_t lastLapBytes = outsideSamples * blockBytes;
  44. safeMemoryCopy(writer, source, lastLapBytes);
  45. }
  46. } else {
  47. // Padd the outside with zeroes.
  48. uint32_t outsideBytes = outsideSamples * blockBytes;
  49. safeMemorySet(target, 0, outsideBytes);
  50. player.sustained = false;
  51. }
  52. } else {
  53. // Only a single copy is needed to fill the output buffer with samples.
  54. safeMemoryCopy(target, source + (player.location * channelCount), playedSamplesPerChannel * blockBytes);
  55. }
  56. player.location += playedSamplesPerChannel;
  57. if (player.repeat) {
  58. while (player.location >= totalSamplesPerChannel) {
  59. player.location -= totalSamplesPerChannel;
  60. }
  61. }
  62. // Apply optional envelope
  63. if (player.envelope.envelopeSettings.used) {
  64. SafePointer<float> currentTarget = target;
  65. for (int32_t s = 0; s < playedSamplesPerChannel; s++) {
  66. float volume = float(player.envelope.getVolume(player.sustained, secondsPerSample));
  67. for (uint32_t c = 0; c < channelCount; c++) {
  68. *currentTarget *= volume;
  69. currentTarget += 1;
  70. }
  71. }
  72. }
  73. }
  74. }