浏览代码

Handling sound requests larger than the fixed period.

David Piuva 9 月之前
父节点
当前提交
890fa3b455
共有 2 个文件被更改,包括 14 次插入6 次删除
  1. 13 6
      Source/DFPSR/api/soundAPI.cpp
  2. 1 0
      Source/DFPSR/api/soundAPI.h

+ 13 - 6
Source/DFPSR/api/soundAPI.cpp

@@ -10,16 +10,23 @@ namespace dsr {
 // See the Source/soundManagers folder for implementations of sound_streamToSpeakers for different operating systems.
 
 bool sound_streamToSpeakers_fixed(int32_t channels, int32_t sampleRate, int32_t periodSamplesPerChannel, std::function<bool(SafePointer<float> fixedTarget)> soundOutput) {
-	int32_t bufferSamplesPerChannel = periodSamplesPerChannel * 2;
+	int32_t bufferSamplesPerChannel = 0;
 	int32_t blockBytes = channels * sizeof(float);
-	Buffer fixedBuffer = buffer_create(bufferSamplesPerChannel * blockBytes);
-	SafePointer<float> bufferPointer = buffer_getSafeData<float>(fixedBuffer, "Fixed size output sound buffer");
+	Buffer fixedBuffer;
+	SafePointer<float> bufferPointer;
 	int32_t writeLocation = 0;
 	int32_t readLocation = 0;
 	return sound_streamToSpeakers(channels, sampleRate, [&](SafePointer<float> dynamicTarget, int32_t requestedSamplesPerChannel) -> bool {
-		// TODO: Allow having a fixed period smaller than what the hardware requests, by delaying buffer allocation.
-		if (requestedSamplesPerChannel > periodSamplesPerChannel) {
-			throwError(U"The fixed period length was smaller than the requested period!\n");
+		// When running for the first time, a buffer large enough for both input and output will be allocated.
+		if (bufferSamplesPerChannel == 0) {
+			// Calculate how much space we need as a minimum.
+			int32_t minimumBufferSize = max(requestedSamplesPerChannel, periodSamplesPerChannel) * 2;
+			// Find a large enough power of two buffer size.
+			bufferSamplesPerChannel = 8192;
+			while (bufferSamplesPerChannel < minimumBufferSize) bufferSamplesPerChannel *= 2;
+			// Allocate the buffer and point to it.
+			fixedBuffer = buffer_create(bufferSamplesPerChannel * blockBytes);
+			bufferPointer = buffer_getSafeData<float>(fixedBuffer, "Fixed size output sound buffer");
 		}
 		int32_t availableSamplesPerChannel = writeLocation - readLocation;
 		if (availableSamplesPerChannel < 0) availableSamplesPerChannel += bufferSamplesPerChannel;

+ 1 - 0
Source/DFPSR/api/soundAPI.h

@@ -29,6 +29,7 @@ namespace dsr {
 	//   The target elements should be filled for indices 0 to (periodSamplesPerChannel * channels) - 1
 	// This allow using SIMD vectorization with a perfectly aligned period size without wasting any padding, even if the hardware's period size is an odd number.
 	// A fixed period can also be used for perfect timing when playing music.
+	// Pre-condition: periodSamplesPerChannel must be a power of two.
 	bool sound_streamToSpeakers_fixed(int32_t channels, int32_t sampleRate, int32_t periodSamplesPerChannel, std::function<bool(dsr::SafePointer<float> target)> soundOutput);
 
 	// A sound buffer with packed channels of 32-bit floats.