浏览代码

Changed the sound backend interface to allow safe vectorization with a known padded buffer size.

David Piuva 2 年之前
父节点
当前提交
66644566a8

+ 2 - 1
README.md

@@ -22,7 +22,8 @@ Real-time dynamic light with depth-based casted shadows and normal mapping at 45
 It is a rendering API, image processing framework and graphical user interface system in a static C++14 library meant to minimize the use of dynamic dependencies in long-term projects while still offering the power to make your own abstractions on top of low-level rendering operations. The core library itself is pure math on a hardware abstraction and can be compiled on most systems using GNU's C++14.
 
 ## Still a public beta
-Don't use it for safety-critical projects unless you verify correctness yourself and take all responsibility. Either way, it's probably a lot safer than using OpenGL, OpenCL or Direct3D simply by being a single implementation where bugs will be mostly the same on each platform. Stack memory for VLA may vary. Test everything with billions of cases.
+Theme, GUI, font and sound APIs are still under active development and may have significant changes before a stable version 1.0 is ready.
+Buffer, file, image, draw, filter, string and time APIs are already quite version stable.
 
 ## Supported CPU hardware:
 * **Intel/AMD** using **SSE2** intrinsics and optional extensions.

+ 2 - 13
Source/soundManagers/AlsaSound.cpp

@@ -3,7 +3,6 @@
 //   Install on Arch: sudo pacman -S libasound-dev
 //   Install on Debian: sudo apt-get install libasound-dev
 
-#include "../DFPSR/includeFramework.h"
 #include "soundManagers.h"
 #include <alsa/asoundlib.h>
 
@@ -33,7 +32,7 @@ static void terminateSound() {
 	}
 }
 
-bool sound_streamToSpeakers(int channels, int sampleRate, std::function<bool(float*, int)> soundOutput) {
+bool sound_streamToSpeakers(int channels, int sampleRate, std::function<bool(SafePointer<float> data, int length)> soundOutput) {
 	int errorCode;
 	if ((errorCode = snd_pcm_open(&pcm, "default", SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
 		terminateSound();
@@ -75,7 +74,7 @@ bool sound_streamToSpeakers(int channels, int sampleRate, std::function<bool(flo
 	allocateBuffers(totalSamples);
 	while (true) {
 		safeMemorySet(floatData, 0, totalSamples * sizeof(float));
-		bool keepRunning = soundOutput(floatData.getUnsafe(), samplesPerChannel);
+		bool keepRunning = soundOutput(floatData, samplesPerChannel);
 		// Convert to target format so that the sound can be played
 		for (uint32_t t = 0; t < samplesPerChannel * channels; t+=8) {
 			// SIMD vectorized sound conversion with scaling and clamping to signed 16-bit integers.
@@ -96,16 +95,6 @@ bool sound_streamToSpeakers(int channels, int sampleRate, std::function<bool(flo
 			outputData[t+5] = (int16_t)upper.y;
 			outputData[t+6] = (int16_t)upper.z;
 			outputData[t+7] = (int16_t)upper.w;
-			/* Reference implementation without SIMD
-			outputData[t+0] = sound_convertF32ToI16(floatData[t+0]);
-			outputData[t+1] = sound_convertF32ToI16(floatData[t+1]);
-			outputData[t+2] = sound_convertF32ToI16(floatData[t+2]);
-			outputData[t+3] = sound_convertF32ToI16(floatData[t+3]);
-			outputData[t+4] = sound_convertF32ToI16(floatData[t+4]);
-			outputData[t+5] = sound_convertF32ToI16(floatData[t+5]);
-			outputData[t+6] = sound_convertF32ToI16(floatData[t+6]);
-			outputData[t+7] = sound_convertF32ToI16(floatData[t+7]);
-			*/
 		}
 		errorCode = snd_pcm_writei(pcm, outputData.getUnsafe(), samplesPerChannel);
 		if (errorCode == -EPIPE) {

+ 2 - 3
Source/soundManagers/WinMMSound.cpp

@@ -1,7 +1,6 @@
 
 // Use -lwinmm for linking to the winmm library in GCC/G++
 
-#include "../DFPSR/includeFramework.h"
 #include "soundManagers.h"
 #include <windows.h>
 #include <mmsystem.h>
@@ -49,7 +48,7 @@ static void terminateSound() {
 	}
 }
 
-bool sound_streamToSpeakers(int channels, int sampleRate, std::function<bool(float*, int)> soundOutput) {
+bool sound_streamToSpeakers(int channels, int sampleRate, std::function<bool(SafePointer<float> data, int length)> soundOutput) {
 	bufferEndEvent = CreateEvent(0, FALSE, FALSE, 0);
 	if (bufferEndEvent == 0) {
 		terminateSound();
@@ -89,7 +88,7 @@ bool sound_streamToSpeakers(int channels, int sampleRate, std::function<bool(flo
 			if ((header[b].dwFlags & WHDR_INQUEUE) == 0) {
 				// When one of the buffers is done playing, generate new sound and write more data to the output.
 				safeMemorySet(floatData, 0, totalSamples * sizeof(float));
-				running = soundOutput(floatData.getUnsafe(), samplesPerChannel);
+				running = soundOutput(floatData, samplesPerChannel);
 				//for (int i = 0; i < totalSamples; i++) {
 				//	outputData[b][i] = sound_convertF32ToI16(floatBuffer[i]);
 				//}

+ 2 - 14
Source/soundManagers/soundManagers.h

@@ -2,19 +2,7 @@
 #ifndef DFPSR_SOUND_API
 #define DFPSR_SOUND_API
 
-#include <functional>
-#include <stdint.h>
-
-inline float sound_convertI16ToF32(int64_t input) {
-	return input * (1.0f / 32767.0f);
-}
-
-inline int sound_convertF32ToI16(float input) {
-	int64_t result = input * 32767.0f;
-	if (result > 32767) { result = 32767; }
-	if (result < -32768) { result = -32768; }
-	return result;
-}
+#include "../DFPSR/includeFramework.h"
 
 // TODO: The float array should be padded to at least 16 bytes for 128-bit SIMD.
 
@@ -23,6 +11,6 @@ inline int sound_convertF32ToI16(float input) {
 // Channels from the same point in time are packed together without any padding in between.
 // Returns false if the backend could not be created.
 // Returns true iff the backend completed all work and terminated safely.
-bool sound_streamToSpeakers(int channels, int sampleRate, std::function<bool(float*, int)> soundOutput);
+bool sound_streamToSpeakers(int channels, int sampleRate, std::function<bool(dsr::SafePointer<float> data, int length)> soundOutput);
 
 #endif

+ 12 - 1
Source/tools/wizard/sound.cpp

@@ -7,6 +7,17 @@ using namespace dsr;
 #include <future>
 #include <atomic>
 
+inline float sound_convertI16ToF32(int64_t input) {
+	return input * (1.0f / 32767.0f);
+}
+
+inline int sound_convertF32ToI16(float input) {
+	int64_t result = input * 32767.0f;
+	if (result > 32767) { result = 32767; }
+	if (result < -32768) { result = -32768; }
+	return result;
+}
+
 static const int outputChannels = 2;
 static const int outputSampleRate = 44100;
 double outputSoundStep = 1.0 / (double)outputSampleRate;
@@ -398,7 +409,7 @@ void stopAllSounds() {
 void sound_initialize() {
 	// Start a worker thread mixing sounds in realtime
 	std::function<void()> task = []() {
-		sound_streamToSpeakers(outputChannels, outputSampleRate, [](float *target, int requestedSamples) -> bool {
+		sound_streamToSpeakers(outputChannels, outputSampleRate, [](SafePointer<float> target, int requestedSamples) -> bool {
 			// Anyone wanting to change the played sounds from another thread will have to wait until this section has finished processing
 			soundMutex.lock();
 				// TODO: Create a graph of filters for different instruments