1 // psp sound module
2 #include "burner.h"
3 #include <math.h>
4 #include <pspaudio.h>
5 
6 static unsigned int nSoundFps;
7 
8 static int nAudLoopLenSample;
9 static int nAudLoopLen;
10 
11 static short* pAudioSndBuf[2] = {NULL, NULL};
12 static int nAudioThreadId = -1;
13 static int nAudioChannel = -1;
14 static volatile int bAudioTerminate = 1;
15 static volatile int nAudioBufIdx = 0;
16 static volatile int nCurrentSeg = 0;
17 
18 extern "C" void pspSoundCopy11025(short *pDest, short *pSrc, int nLen);
19 extern "C" void pspSoundCopy22050(short *pDest, short *pSrc, int nLen);
20 extern "C" void pspSoundCopy44100(short *pDest, short *pSrc, int nLen);
21 
22 static void (*pspSoundCopy) (short *pDest, short *pSrc, int nLen);
23 
24 /** SOUND THREAD **/
25 
AudioChannelThread(SceSize args,void * argp)26 static int AudioChannelThread(SceSize args, void *argp)
27 {
28 	while (!bAudioTerminate) {
29 		if (bAudPlaying && (nCurrentSeg == nAudSegCount)) {
30 			nAudioBufIdx ^= 1;
31 			nCurrentSeg = 0;
32 			sceAudioOutputPannedBlocking(nAudioChannel, PSP_AUDIO_VOLUME_MAX, PSP_AUDIO_VOLUME_MAX, pAudioSndBuf[1 - nAudioBufIdx]);
33 		//} else {
34 		//	sceKernelSleepThread();
35 		}
36 	}
37 
38 	sceKernelExitThread(0);
39 
40 	return 0;
41 }
42 
43 /************************************/
44 
pspBlankSound()45 static int pspBlankSound()
46 {
47 	if (pAudioSndBuf[0]) {
48 		/* Check to see if there's any Cache issue between the CPU and the sound hardware */
49 		memset(pAudioSndBuf[0], 0, (nAudLoopLen << 1) + (nAudSegLen << 2));
50 	}
51 
52 	return 0;
53 }
54 
pspSoundGetNextSoundFiller(int)55 static int pspSoundGetNextSoundFiller(int)							// int bDraw
56 {
57 	if (nAudNextSound == NULL) {
58 		return 1;
59 	}
60 	memset(nAudNextSound, 0, nAudSegLen << 2);						// Write silence into the buffer
61 
62 	return 0;
63 }
64 
65 int (*pspSoundGetNextSound) (int bDraw) = pspSoundGetNextSoundFiller;	// Callback used to request more sound
66 
pspSoundCheck()67 static int pspSoundCheck()
68 {
69 	char *pData;
70 	int nPspSegLen;
71 
72 	if (pAudioSndBuf[0] == NULL)
73 		return 1;
74 
75 	if (nCurrentSeg == nAudSegCount) {
76 		//Sleep(2);													// Don't need to do anything for a bit
77 		return 0;
78 	}
79 
80 	pData = (char*)pAudioSndBuf[nAudioBufIdx];
81 	nPspSegLen = nAudSegLen;
82 
83 	if (nAudSampleRate == 22050)
84 		nPspSegLen <<= 1;
85 	else if (nAudSampleRate == 11025)
86 		nPspSegLen <<= 2;
87 
88 	pData += nCurrentSeg * nPspSegLen;
89 
90 	pspSoundCopy((short*)pData, nAudNextSound, nAudSegLen);
91 	pspSoundGetNextSound(1);									// get more sound into nAudNextSound
92 
93 	nCurrentSeg++;
94 	//if ((nCurrentSeg == nAudSegCount) && (nAudioThreadId >= 0)) {
95 	//	sceKernelWakeupThread(nAudioThreadId);
96 	//}
97 	if (bAudPlaying && (nCurrentSeg == nAudSegCount)) {
98 		sceAudioOutputPanned(nAudioChannel, PSP_AUDIO_VOLUME_MAX, PSP_AUDIO_VOLUME_MAX, pAudioSndBuf[nAudioBufIdx]);
99 		nAudioBufIdx ^= 1;
100 		nCurrentSeg = 0;
101 	}
102 
103 	return 0;
104 }
105 
pspSetCallback(int (* pCallback)(int))106 static int pspSetCallback(int (*pCallback)(int))
107 {
108 	if (pCallback == NULL) {
109 		pspSoundGetNextSound = pspSoundGetNextSoundFiller;
110 	} else {
111 		pspSoundGetNextSound = pCallback;
112 	}
113 	return 0;
114 }
115 
pspSoundExit()116 static int pspSoundExit()
117 {
118 	bAudPlaying = 0;
119 	bAudioTerminate = 1;
120 	bAudOkay = 0;													// This module is no longer okay
121 
122 	if (nAudioThreadId >= 0) {
123 		sceKernelDeleteThread(nAudioThreadId);
124 		nAudioThreadId = -1;
125 	}
126 
127 	if (nAudioChannel >= 0) {
128 		sceAudioChRelease(nAudioChannel);
129 		nAudioChannel = -1;
130 	}
131 
132 	if (pAudioSndBuf[0]) {
133 		free(pAudioSndBuf[0]);
134 		pAudioSndBuf[0] = NULL;
135 		pAudioSndBuf[1] = NULL;
136 		nAudNextSound = NULL;
137 	}
138 
139 	return 0;
140 }
141 
pspSoundInit()142 static int pspSoundInit()
143 {
144 	//if (nAudSampleRate <= 0) {
145 	//	return 1;
146 	//}
147 	if ((nAudSampleRate != 11025) && (nAudSampleRate != 22050) && (nAudSampleRate != 44100)) {
148 		return 1;
149 	}
150 	nSoundFps = nAppVirtualFps;
151 	nAudSegLen = (nAudSampleRate * 100 + (nSoundFps >> 1)) / nSoundFps;
152 	nAudLoopLenSample = nAudSegLen * nAudSegCount;
153 
154 	if (nAudSampleRate == 11025) {
155 		nAudLoopLenSample << 2;
156 		pspSoundCopy = pspSoundCopy11025;
157 	} else if (nAudSampleRate == 22050) {
158 		nAudLoopLenSample << 1;
159 		pspSoundCopy = pspSoundCopy22050;
160 	} else {
161 		pspSoundCopy = pspSoundCopy44100;
162 	}
163 
164 	nAudLoopLenSample = PSP_AUDIO_SAMPLE_ALIGN(nAudLoopLenSample);
165 	nAudLoopLen = nAudLoopLenSample << 2;
166 
167 	pAudioSndBuf[0] = (short*)malloc((nAudLoopLen << 1) + (nAudSegLen << 2));
168 	pAudioSndBuf[1] = pAudioSndBuf[0] + (nAudLoopLenSample << 1);
169 	nAudNextSound = pAudioSndBuf[1] + (nAudLoopLenSample << 1);		// The next sound block to put in the stream
170 
171 	if (pAudioSndBuf[0] == NULL) {
172 		pspSoundExit();
173 		return 1;
174 	}
175 
176 	nAudioChannel = sceAudioChReserve(PSP_AUDIO_NEXT_CHANNEL, nAudLoopLenSample, PSP_AUDIO_FORMAT_STEREO);
177 
178 	if (nAudioChannel < 0) {
179 		pspSoundExit();
180 		return 1;
181 	}
182 
183 	//nAudioThreadId = sceKernelCreateThread("audio_thread", AudioChannelThread, 0x18, 0x1000, PSP_THREAD_ATTR_USER, NULL);
184 
185 	//if (nAudioThreadId < 0) {
186 	//	pspSoundExit();
187 	//	return 1;
188 	//}
189 
190 	memset(pAudioSndBuf[0], 0, (nAudLoopLen << 1) + (nAudSegLen << 2));
191 
192 	bAudioTerminate = 0;
193 
194 	//if (sceKernelStartThread(nAudioThreadId, 0, NULL)) {
195 	//	pspSoundExit();
196 	//	return 1;
197 	//}
198 
199 	bAudOkay = 1;											// This module was initted okay
200 	return 0;
201 }
202 
pspSoundPlay()203 static int pspSoundPlay()
204 {
205 	if (bAudOkay == 0) {
206 		return 1;
207 	}
208 	pspBlankSound();
209 	bAudPlaying = 1;
210 
211 	return 0;
212 }
213 
pspSoundStop()214 static int pspSoundStop()
215 {
216 	bAudPlaying = 0;
217 	return 0;
218 }
219 
pspSoundSetVolume()220 static int pspSoundSetVolume()
221 {
222 	return 1;
223 }
224 
pspSoundGetSettings(InterfaceInfo * pInfo)225 static int pspSoundGetSettings(InterfaceInfo* pInfo)
226 {
227 	{
228 	}
229 	return 1;
230 }
231 
232 struct AudOut AudOutPSP = { pspBlankSound, pspSoundCheck, pspSoundInit, pspSetCallback, pspSoundPlay, pspSoundStop, pspSoundExit, pspSoundSetVolume, pspSoundGetSettings, _T("psp audio output") };
233