@@ -87,9 +87,10 @@ static uint8_t vsync; /* 0 (Disabled), 1 (Enabled), 2 (Dynamic) */
87
87
#define SOUND_BLOCK_COUNT 7
88
88
#define SOUND_BUFFER_CHUNK (2*54000/50) // max.rate/min.frames in stereo
89
89
90
+ static short sndBuffer_emu [SOUND_BUFFER_CHUNK + 4 ]; // 4 for sample rounding overhang
90
91
static short __attribute__((aligned (4 ))) sndBuffer [SOUND_BUFFER_CHUNK * SOUND_BLOCK_COUNT ];
91
92
static short __attribute__((aligned (4 ))) nulBuffer [SOUND_BUFFER_CHUNK ];
92
- static short * snd_playptr , * sndBuffer_endptr ;
93
+ static short * snd_playptr , * sndBuffer_ptr , * sndBuffer_endptr ;
93
94
static int samples_made , samples_done , samples_block ;
94
95
95
96
static int sound_thread_exit = 0 , sound_stopped = 1 ;
@@ -122,32 +123,86 @@ static void writeSound(int len)
122
123
123
124
if (samples_made - samples_done < samples_block * (SOUND_BLOCK_COUNT - 2 ) - 4 ) {
124
125
samples_made += len / 2 ;
125
- PicoIn .sndOut += len / 2 ;
126
+ sndBuffer_ptr += len / 2 ;
127
+ l = sndBuffer_ptr - sndBuffer ;
128
+
129
+ if (sndBuffer_ptr > sndBuffer_endptr )
130
+ sndBuffer_endptr = sndBuffer_ptr ;
131
+ if (l > sizeof (sndBuffer )/2 )
132
+ lprintf ("snd ovrn %d %d\n" , len , sndBuffer_ptr - sndBuffer );
133
+ if (l > samples_block * (SOUND_BLOCK_COUNT - 2 )) {
134
+ sndBuffer_endptr = sndBuffer_ptr ;
135
+ sndBuffer_ptr = sndBuffer ;
136
+ }
126
137
} else
127
138
lprintf ("ovfl %d\n" , samples_made - samples_done );
128
- if (sndBuffer_endptr < PicoIn .sndOut )
129
- sndBuffer_endptr = PicoIn .sndOut ;
130
-
131
- l = PicoIn .sndOut - sndBuffer ;
132
- if (l > sizeof (sndBuffer )/2 )
133
- lprintf ("ovrn %d %d\n" , len , PicoIn .sndOut - sndBuffer );
134
- if (l > samples_block * (SOUND_BLOCK_COUNT - 2 )) {
135
- sndBuffer_endptr = PicoIn .sndOut ;
136
- PicoIn .sndOut = sndBuffer ;
137
- }
138
139
139
140
// signal the snd thread
140
141
SignalSema (sound_sem );
141
142
}
142
143
144
+ static void writeSound_44100 (int len )
145
+ {
146
+ writeSound (len );
147
+ PicoIn .sndOut = sndBuffer_ptr ;
148
+ }
149
+
150
+ static void writeSound_22050_stereo (int len )
151
+ {
152
+ short * p = sndBuffer_ptr ;
153
+ int i ;
154
+
155
+ for (i = 0 ; i < len / 2 ; i += 2 , p += 4 ) {
156
+ p [0 ] = p [2 ] = PicoIn .sndOut [i ];
157
+ p [1 ] = p [3 ] = PicoIn .sndOut [i + 1 ];
158
+ }
159
+ writeSound (2 * len );
160
+ }
161
+
162
+ static void writeSound_22050_mono (int len )
163
+ {
164
+ short * p = sndBuffer_ptr ;
165
+ int i ;
166
+
167
+ for (i = 0 ; i < len / 2 ; i ++ , p += 2 ) {
168
+ p [0 ] = p [1 ] = PicoIn .sndOut [i ];
169
+ }
170
+ writeSound (2 * len );
171
+ }
172
+
173
+ static void writeSound_11025_stereo (int len )
174
+ {
175
+ short * p = sndBuffer_ptr ;
176
+ int i ;
177
+
178
+ for (i = 0 ; i < len / 2 ; i += 2 , p += 8 ) {
179
+ p [0 ] = p [2 ] = p [4 ] = p [6 ] = PicoIn .sndOut [i ];
180
+ p [1 ] = p [3 ] = p [5 ] = p [7 ] = PicoIn .sndOut [i + 1 ];
181
+ }
182
+ writeSound (4 * len );
183
+ }
184
+
185
+ static void writeSound_11025_mono (int len )
186
+ {
187
+ short * p = sndBuffer_ptr ;
188
+ int i ;
189
+
190
+ for (i = 0 ; i < len / 2 ; i ++ , p += 4 ) {
191
+ p [0 ] = p [1 ] = p [2 ] = p [3 ] = PicoIn .sndOut [i ];
192
+ }
193
+ writeSound (4 * len );
194
+ }
195
+
196
+ #define PS2_RATE 44100 // PicoIn.sndRate
197
+
143
198
static void resetSound ()
144
199
{
145
200
struct audsrv_fmt_t format ;
146
201
int stereo = (PicoIn .opt & 8 )>>3 ;
147
202
int ret ;
148
203
149
204
format .bits = 16 ;
150
- format .freq = PicoIn . sndRate ;
205
+ format .freq = PS2_RATE ;
151
206
format .channels = stereo ? 2 : 1 ;
152
207
ret = audsrv_set_format (& format );
153
208
if (ret < 0 ) {
@@ -170,14 +225,10 @@ static int sound_thread(void *argp)
170
225
// if there aren't enough samples, queue silence
171
226
int queued = audsrv_queued ()/2 ;
172
227
while (queued < 2 * samples_block ) {
173
- short * sndOut = PicoIn .sndOut , * sndEnd = sndBuffer_endptr ;
174
-
175
228
// compute sample chunk size
176
- int buflen = sndEnd - snd_playptr ;
177
- if (sndOut >= snd_playptr )
178
- buflen = sndOut - snd_playptr ;
179
- if (buflen > samples_made - samples_done )
180
- buflen = samples_made - samples_done ;
229
+ int buflen = samples_made - samples_done ;
230
+ if (buflen > sndBuffer_endptr - snd_playptr )
231
+ buflen = sndBuffer_endptr - snd_playptr ;
181
232
if (buflen > 3 * samples_block - queued )
182
233
buflen = 3 * samples_block - queued ;
183
234
@@ -241,7 +292,7 @@ static void sound_init(void)
241
292
thread .initial_priority = 40 ;
242
293
thid = CreateThread (& thread );
243
294
244
- samples_block = 22050 / 50 ; // needs to be initialized before thread start
295
+ samples_block = PS2_RATE / 60 ; // needs to be initialized before thread start
245
296
if (thid >= 0 ) {
246
297
ret = StartThread (thid , NULL );
247
298
if (ret < 0 ) lprintf ("sound_init: StartThread returned %08x\n" , ret );
@@ -255,7 +306,7 @@ static void sound_init(void)
255
306
void pemu_sound_start (void ) {
256
307
static int PsndRate_old = 0 , PicoOpt_old = 0 , pal_old = 0 ;
257
308
static int mp3_init_done ;
258
- int ret , stereo ;
309
+ int ret , stereo , factor ;
259
310
260
311
samples_made = samples_done = 0 ;
261
312
@@ -279,14 +330,22 @@ void pemu_sound_start(void) {
279
330
PsndRerate (Pico .m .frame_count ? 1 : 0 );
280
331
}
281
332
stereo = (PicoIn .opt & 8 )>>3 ;
282
- samples_block = (PicoIn .sndRate / (Pico .m .pal ? 50 : 60 )) * (stereo ? 2 : 1 );
333
+
334
+ factor = PS2_RATE / PicoIn .sndRate ;
335
+ samples_block = (PS2_RATE / (Pico .m .pal ? 50 : 60 )) * (stereo ? 2 : 1 );
283
336
284
337
lprintf ("starting audio: %i, len: %i, stereo: %i, pal: %i, block samples: %i\n" ,
285
338
PicoIn .sndRate , Pico .snd .len , stereo , Pico .m .pal , samples_block );
286
339
287
340
resetSound ();
288
- PicoIn .writeSound = writeSound ;
289
- snd_playptr = PicoIn .sndOut = sndBuffer_endptr = sndBuffer ;
341
+ switch (factor ) {
342
+ case 1 : PicoIn .writeSound = stereo ? writeSound_44100 :writeSound_44100 ; break ;
343
+ case 2 : PicoIn .writeSound = stereo ? writeSound_22050_stereo :writeSound_22050_mono ; break ;
344
+ case 4 : PicoIn .writeSound = stereo ? writeSound_11025_stereo :writeSound_11025_mono ; break ;
345
+ }
346
+ sndBuffer_endptr = sndBuffer ;
347
+ snd_playptr = sndBuffer_ptr = sndBuffer ;
348
+ PicoIn .sndOut = (factor == 1 ? sndBuffer_ptr : sndBuffer_emu );
290
349
291
350
PsndRate_old = PicoIn .sndRate ;
292
351
PicoOpt_old = PicoIn .opt ;
0 commit comments