From 3469b8f8c7ff27e9ebe745c1c7d86c8e2e5be157 Mon Sep 17 00:00:00 2001 From: diamant3 Date: Fri, 16 Sep 2022 16:46:43 +0800 Subject: [PATCH] add audio sample --- README.md | 246 ++++++++++++++++++++++++++++++++++++++++++++++- images/audio.png | Bin 0 -> 1212 bytes 2 files changed, 244 insertions(+), 2 deletions(-) create mode 100644 images/audio.png diff --git a/README.md b/README.md index 47534a4..e747238 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ Below are some basic examples of programs for the PSP. More can be found [here]( ![](images/hello.png?raw=true) -This is a simple Hello World program for the PSP. Click on details below for the to see the code and how to build it. +This is a simple Hello World program for the PSP. Click on the details below to see the code and how to build it.

@@ -137,7 +137,7 @@ This will result in an EBOOT.PBP file in the build directory. Put it in a direct ![](images/shape.png?raw=true) -This is a simple a simple square drawn on the PSP. It uses the native libgu library. Click on details below for the to see the code and how to build it. +This is a simple square drawn on the PSP. It uses the native libgu library. Click on the details below to see the code and how to build it.

@@ -423,6 +423,248 @@ make

+### Audio + +![](images/audio.png?raw=true) + +This is a simple program to use the audio of the PSP with minimal effort. It will produce sound depending on the selected waveform and can set the frequency for every waveform. Click on the details below to see the code and how to build it. + +

+ +main.c: + +
+#include <pspkernel.h>
+#include <pspdebug.h>
+#include <pspaudiolib.h>
+#include <pspaudio.h>
+#include <pspdisplay.h>
+#include <pspctrl.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <limits.h>
+
+PSP_MODULE_INFO("audio", 0, 1, 1);
+PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER | THREAD_ATTR_VFPU);
+
+#define printf	pspDebugScreenPrintf
+
+/* Exit callback */
+int exitCallback(int arg1, int arg2, void *common) {
+	sceKernelExitGame();
+	return 0;
+}
+
+/* Callback thread */
+int callbackThread(SceSize args, void *argp) {
+	int cbid;
+
+	cbid = sceKernelCreateCallback("Exit Callback", (void*) exitCallback, NULL);
+	sceKernelRegisterExitCallback(cbid);
+	sceKernelSleepThreadCB();
+
+	return 0;
+}
+
+/* Sets up the callback thread and returns its thread id */
+int setupCallbacks(void) {
+	int thid = 0;
+
+	thid = sceKernelCreateThread("update_thread", callbackThread, 0x11, 0xFA0, 0, 0);
+	if (thid >= 0) {
+		sceKernelStartThread(thid, 0, 0);
+	}
+	return thid;
+}
+
+/* Main code */
+
+const float PI = 3.1415926535897932f;
+const int sampleRate = 44100;
+float frequency = 440.0f;
+float currentTime = 0;
+int function = 0;
+
+typedef struct {
+        short l, r;
+} sample_t;
+
+float currentFunction(const float time) {
+    double x;
+	float t = modf((time / (2 * PI)), &x);
+
+    switch(function) {
+		case 0: // SINE
+	    	return sinf(time);
+		case 1: // SQUARE
+	        if (t < 0.5f) {
+	            return -0.2f;
+	        } else {
+	            return 0.2f;
+	        }
+		case 2: // TRIANGLE
+	        if (t < 0.5f) {
+	            return (t * 2.0f) - 0.5f;
+	        } else {
+	            return 0.5f - (t - 0.5f) * 2.0f;
+	        }
+		default:
+ 	        return 0.0f;
+    }
+}
+
+/* This function gets called by pspaudiolib every time the
+   audio buffer needs to be filled. The sample format is
+   16-bit, stereo. */
+void audioCallback(void* buf, unsigned int length, void *userdata) {
+    const float sampleLength = 1.0f / sampleRate;
+	const float scaleFactor = SHRT_MAX - 1.0f;
+    static float freq0 = 440.0f;
+    sample_t* ubuf = (sample_t*) buf;
+	int i;
+	
+	if (frequency != freq0) {
+	        currentTime *= (freq0 / frequency);
+	}
+	for (i = 0; i < length; i++) {
+	    short s = (short) (scaleFactor * currentFunction(2.0f * PI * frequency * currentTime));
+		ubuf[i].l = s;
+		ubuf[i].r = s;
+		currentTime += sampleLength;
+	}
+	if (currentTime * frequency > 1.0f) {
+	    double d;
+		currentTime = modf(currentTime * frequency, &d) / frequency;
+	}
+
+	freq0 = frequency;
+}
+
+/* Read the analog stick and adjust the frequency */
+void controlFrequency(void) {
+    static int oldButtons = 0;
+	const int zones[6] = {30, 70, 100, 112, 125, 130};
+	const float response[6] = {0.0f, 0.1f, 0.5f, 1.0f, 4.0f, 8.0f};
+	const float minFreq = 32.0f;
+	const float maxFreq = 7040.0f;
+	SceCtrlData pad;
+	float direction;
+	int changedButtons;
+	int i, v;
+
+	sceCtrlReadBufferPositive(&pad, 1);
+
+	v = pad.Ly - 128;
+	if (v < 0) {
+   	    direction = 1.0f;
+		v = -v;
+	} else {
+	    direction = -1.0f;
+	}
+
+	for (i = 0; i < 6; i++) {
+	    if (v < zones[i]) {
+		    frequency += (response[i] * direction);
+			break;
+	    }
+	}
+
+	if (frequency < minFreq) {
+	    frequency = minFreq;
+	} else if (frequency > maxFreq) {
+	    frequency = maxFreq;
+	}
+
+	changedButtons = pad.Buttons & (~oldButtons);
+	if (changedButtons & PSP_CTRL_CROSS) {
+	    function++;
+	    if (function > 2) {
+	        function = 0;
+	    }
+	}
+
+	oldButtons = pad.Buttons;
+}
+
+int main(void) {
+	pspDebugScreenInit();
+	setupCallbacks();
+
+	pspAudioInit();
+	pspAudioSetChannelCallback(0, audioCallback, NULL);
+
+	sceCtrlSetSamplingCycle(0);
+	sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG);
+
+	printf("Press up and down to select frequency\nPress X to change function\n");
+	
+	while(1) {
+		sceDisplayWaitVblankStart();
+		pspDebugScreenSetXY(0,2);
+		printf("freq = %.2f \n", frequency);
+
+		switch(function) {
+			case 0:
+				printf("SINE WAVE. \n");
+				break;
+			case 1:
+		  		printf("SQUARE WAVE. \n");
+				break;
+			case 2:
+		  		printf("TRIANGLE WAVE. \n");
+				break;
+		}
+
+		controlFrequency();
+	}
+
+	return 0;
+}
+
+ +CMakeLists.txt: + +
+cmake_minimum_required(VERSION 3.0)
+
+project(audio)
+
+add_executable(${PROJECT_NAME} main.c)
+
+target_link_libraries(${PROJECT_NAME} PRIVATE
+    pspdebug
+    pspdisplay
+    pspge
+    pspctrl
+    pspaudio
+    pspaudiolib
+    psputility
+)
+
+# Create an EBOOT.PBP file
+create_pbp_file(
+    TARGET ${PROJECT_NAME}
+    ICON_PATH NULL
+    BACKGROUND_PATH NULL
+    PREVIEW_PATH NULL
+    TITLE ${PROJECT_NAME}
+)
+
+ +Building can be done with: + +
+mkdir build && cd build
+psp-cmake ..
+make
+
+ +

This will result in an EBOOT.PBP file in the build directory. Put it in a directory in ms0:/PSP/GAME/ and the PSP can run it.

+ +

+ ### Using SDL2 ![](images/sdl2.png?raw=true) diff --git a/images/audio.png b/images/audio.png new file mode 100644 index 0000000000000000000000000000000000000000..34fbd0d3f5095fe6628797e2fb089e7480fb1932 GIT binary patch literal 1212 zcmeAS@N?(olHy`uVBq!ia0y~yV0-|?0vt?0k>@G~w}BL6age(c!@6@aFBuqE$~;{h zLn>~)y?e1}u>lWj!2kdLSy=tNT+!85rZyvVZm;~Vbd}%#tQS0yzR$n-VOd*u`M)>s)BeT(_!a*% z=9KtKT~&wT_ve3C>%WVwdpalE&LKbV(izj4`uoHeeD1C{a`@i=C$Zt3{H~Ki?r&pG zIp;q7f3N>#!Ec7WS)r@FWELO%GK*(d!4b8|yPwpF9XtEy#yY7L0gq0Y@7wI2_0&eo zVfzjT%aE;aVkU1DI{U{|^4fyi*Tj<+3vP>PmeWe~-)Au;M~(4UfjR&G!pc-jc@B+x z#sz$9V)y@I`@Tacu40p4SkC-H^@!b)L9P{PtBU@b>Nx1HZ{a%f;R8c$qqHXV+-r1Dz>;7HCQo%Q$c~52M<4txi7Jgs&D$A%*l zw+k`nPjr;uw_^`~)eGZ)srIiW-fp~Wtzhh%`Lu8QNrtr{Oy#^6R)>XlY{*@gz2k!6 zU9Y!WCeN44Vzlafz+_@$>9Ae+*8=_5Qh7_y-Tbs(<&^1*!wcm7b_ZrxiY;h#zk9D{ zDcc^ksdcO0T0WkhKY6YqgShMA@0^~0ch-rW+c#~!@B`gTS5I2j{N9;m5gYjY_GYK& z@%8KZpNBA4M6TOa#&GN+ZDR=QoiU`2YJdZczWf4u$PQ(-L1H_ upEi8^7&2FG(m(!CV2&9D)C_?KX8#yeayGp%;rjjzWUi;HpUXO@geCxgSFKwB literal 0 HcmV?d00001