Previous 15994 Revisions Next

r908 Saturday 1st September, 2007 at 15:58:41 UTC by R. Belmont
[SDLMESS] enik's rewritten audio, should fix pops/crackles when at 100% speed.
[src/osd/sdl]sound.c

src/osd/sdl/sound.c
r907r908
3737//============================================================
3838
3939// number of samples per SDL callback
40#define SDL_XFER_SAMPLES      512
40static int sdl_xfer_samples = 512;
41static int stream_in_initialized = 0;
42static int stream_loop = 0;
4143
4244// maximum audio latency
4345#define MAX_AUDIO_LATENCY      10
r907r908
5658
5759static UINT32            stream_buffer_size;
5860static UINT32            stream_buffer_in;
59static volatile UINT32          stream_write_cursor;
6061
6162// buffer over/underflow counts
6263static int            buffer_underflows;
r907r908
143144      if (video_get_throttle())
144145      {
145146         pstart = stream_playpos;
146         pend = (pstart + SDL_XFER_SAMPLES);
147         pend = (pstart + sdl_xfer_samples);
147148         lstart = offset;
148149         lend = lstart+size;
149150         while (((pstart >= lstart) && (pstart <= lend)) ||
r907r908
156157            #endif*/
157158
158159            pstart = stream_playpos;
159            pend = pstart + SDL_XFER_SAMPLES;
160            pend = pstart + sdl_xfer_samples;
160161         }
161162      }
162163
r907r908
182183      *buffer1 = &stream_buffer[offset];
183184   }
184185
185   #if LOG_SOUND
186//   fprintf(sound_log, "locking %ld bytes at offset %ld (total %d, playpos %d): len1 %ld len2 %ld\n",
187//      size, offset, stream_buffer_size, stream_playpos, *length1, *length2);
188   #endif
186#if LOG_SOUND
187   fprintf(sound_log, "locking %ld bytes at offset %ld (total %d, playpos %d): len1 %ld len2 %ld\n",
188           size, offset, stream_buffer_size, stream_playpos, *length1, *length2);
189#endif
189190
190191   return 0;
191192}
r907r908
199200   if (!buf_locked)
200201      SDL_UnlockAudio();
201202
202   #if LOG_SOUND
203//   fprintf(sound_log, "unlocking\n");
204   #endif
203#if LOG_SOUND
204   fprintf(sound_log, "unlocking\n");
205#endif
205206}
206207
207208//============================================================
r907r908
238239   }
239240
240241   // adjust the input pointer
241   stream_buffer_in = (stream_buffer_in + bytes_to_copy) % stream_buffer_size;
242   stream_buffer_in += bytes_to_copy;
243   if (stream_buffer_in >= stream_buffer_size)
244   {
245      stream_buffer_in -= stream_buffer_size;
246      stream_loop = 1;
247#if LOG_SOUND
248      fprintf(sound_log, "stream_loop set to 1 (stream_buffer_in looped)\n");
249#endif
250   }
242251
243252   // copy the first chunk
244253   cur_bytes = (bytes_to_copy > length1) ? length1 : bytes_to_copy;
r907r908
270279   if (Machine->sample_rate != 0 && stream_buffer)
271280   {
272281      int bytes_this_frame = samples_this_frame * sizeof(INT16) * 2;
273      int play_position, write_position, stream_in;
282      int play_position, write_position, orig_write, stream_in;
274283
275284      play_position = stream_playpos;
276285
277286      write_position = stream_playpos + ((Machine->sample_rate / 50) * sizeof(INT16) * 2);
287      orig_write = write_position;
278288
279      // normalize the write position so it is always after the play position
280      if (write_position < play_position)
281         write_position += stream_buffer_size;
289      if (!stream_in_initialized)
290      {
291         stream_in = stream_buffer_in = (write_position + stream_buffer_size) / 2;
282292
283      // normalize the stream in position so it is always after the write position
284      stream_in = stream_buffer_in;
285      if (stream_in < write_position)
286         stream_in += stream_buffer_size;
293#if LOG_SOUND
294         fprintf(sound_log, "stream_in = %d\n", (int)stream_in);
295         fprintf(sound_log, "stream_playpos = %d\n", (int)stream_playpos);
296         fprintf(sound_log, "write_position = %d\n", (int)write_position);
297#endif
287298
288      // now we should have, in order:
289      //    <------pp---wp---si--------------->
299         // start playing
300         SDL_PauseAudio(0);
290301
291      // if we're between play and write positions, then bump forward, but only in full chunks
292      while (stream_in < write_position)
302         stream_in_initialized = 1;
303      }
304      else
293305      {
294//         printf("Underflow: PP=%d  WP=%d(%d)  SI=%d(%d)  BTF=%d\n", (int)play_position, (int)write_position, (int)orig_write, (int)stream_in, (int)stream_buffer_in, (int)bytes_this_frame);
295         buffer_underflows++;
296         stream_in += samples_this_frame;
306         // normalize the stream in position
307         stream_in = stream_buffer_in;
308         if (stream_in < write_position && stream_loop == 1)
309            stream_in += stream_buffer_size;
310
311         // now we should have, in order:
312         //    <------pp---wp---si--------------->
313
314         // if we're between play and write positions, then bump forward, but only in full chunks
315         while (stream_in < write_position)
316         {
317#if LOG_SOUND
318            fprintf(sound_log, "Underflow: PP=%d  WP=%d(%d)  SI=%d(%d)  BTF=%d\n", (int)play_position, (int)write_position, (int)orig_write, (int)stream_in, (int)stream_buffer_in, (int)bytes_this_frame);
319#endif
320            buffer_underflows++;
321            stream_in += samples_this_frame;
322         }
323
324         // if we're going to overlap the play position, just skip this chunk
325         if (stream_in + bytes_this_frame > play_position + stream_buffer_size)
326         {
327#if LOG_SOUND
328            fprintf(sound_log, "Overflow: PP=%d  WP=%d(%d)  SI=%d(%d)  BTF=%d\n", (int)play_position, (int)write_position, (int)orig_write, (int)stream_in, (int)stream_buffer_in, (int)bytes_this_frame);
329#endif
330            buffer_overflows++;
331            return;
332         }
297333      }
298334
299      // if we're going to overlap the play position, just skip this chunk
300      if (stream_in + bytes_this_frame > play_position + stream_buffer_size)
335      if (stream_in >= stream_buffer_size)
301336      {
302//         printf("Overflow: PP=%d  WP=%d(%d)  SI=%d(%d)  BTF=%d\n", (int)play_position, (int)write_position, (int)orig_write, (int)stream_in, (int)stream_buffer_in, (int)bytes_this_frame);
303         buffer_overflows++;
304         return;
337         stream_in -= stream_buffer_size;
338         stream_loop = 1;
339#if LOG_SOUND
340         fprintf(sound_log, "stream_loop set to 1 (stream_in looped)\n");
341#endif
305342      }
306343
307344      // now we know where to copy; let's do it
308      stream_buffer_in = stream_in % stream_buffer_size;
345      stream_buffer_in = stream_in;
309346      copy_sample_data(buffer, bytes_this_frame);
310347   }
311348}
r907r908
356393{
357394   int len1, len2;
358395
359   if ((stream_playpos+len) > stream_buffer_size)
396   if (stream_in_initialized == 1 && stream_loop == 0
397       && (stream_playpos+len) > stream_buffer_in)
360398   {
399#if LOG_SOUND
400      // I solved a crash by comment out a printf at sdl_callback. so
401      // I think this fprintf could cause a crash too (well, it works
402      // fine to me) if output is slow and sdl_callback is called
403      // again before exit the function (could be possible?).
404      //fprintf(sound_log, "Underflow at sdl_callback: SPP=%d  SBI=%d  Len=%d\n", (int)stream_playpos, (int)stream_buffer_in, (int)len);
405#endif
406      len1 = stream_buffer_in - stream_playpos;
407      len2 = 0;
408   }
409   else if ((stream_playpos+len) > stream_buffer_size)
410   {
361411      len1 = stream_buffer_size - stream_playpos;
362412      len2 = len - len1;
363413   }
r907r908
384434   }
385435
386436   // move the play cursor
387   stream_playpos += len;
388   stream_playpos %= stream_buffer_size;
437   stream_playpos += len1 + len2;
438   if (stream_playpos >= stream_buffer_size)
439   {
440      stream_playpos -= stream_buffer_size;
441      stream_loop = 0;
442#if LOG_SOUND
443      fprintf(sound_log, "stream_loop set to 0 (stream_playpos looped)\n");
444#endif
445   }
389446
390   // always keep the write cursor just ahead of the play position
391   stream_write_cursor = stream_playpos + len;
392   stream_write_cursor %= stream_buffer_size;
393
394   #if LOG_SOUND
395//   fprintf(sound_log, "callback: xfer len1 %d len2 %d, playpos %d, wcursor %d\n",
396//      len1, len2, stream_playpos, stream_write_cursor);
397   #endif
447#if LOG_SOUND
448   fprintf(sound_log, "callback: xfer len1 %d len2 %d, playpos %d\n",
449           len1, len2, stream_playpos);
450#endif
398451}
399452
400453
r907r908
405458{
406459   int         n_channels = 2;
407460   int         audio_latency;
408   SDL_AudioSpec    aspec;
461   SDL_AudioSpec    aspec, obtained;
462   char audio_driver[16];
409463
410464   initialized_audio = 0;
411465
r907r908
413467   aspec.freq = Machine->sample_rate;
414468   aspec.format = AUDIO_S16SYS;   // keep endian independant
415469   aspec.channels = n_channels;
416   aspec.samples = SDL_XFER_SAMPLES;
470   aspec.samples = sdl_xfer_samples;
417471   aspec.callback = sdl_callback;
418472   aspec.userdata = 0;
419473
420   if (SDL_OpenAudio(&aspec, NULL) < 0)
474   if (SDL_OpenAudio(&aspec, &obtained) < 0)
421475      goto cant_start_audio;
422476
423477   initialized_audio = 1;
424478   snd_enabled = 1;
425479
480   SDL_AudioDriverName(audio_driver, sizeof(audio_driver));
481   mame_printf_verbose("Audio initialized - driver: %s, frequency: %d, "
482                       "channels: %d, samples: %d\n", audio_driver,
483                       obtained.freq, obtained.channels, obtained.samples);
484
485   sdl_xfer_samples = obtained.samples;
486
426487   audio_latency = options_get_int(mame_options(), SDLOPTION_AUDIO_LATENCY);
427488
428489   // pin audio latency
r907r908
441502   if (stream_buffer_size < 1024)
442503      stream_buffer_size = 1024;
443504
444#if LOG_SOUND
445   fprintf(sound_log, "stream_buffer_size = %d\n", stream_buffer_size);
446#endif
447
448505   // create the buffers
449506   if (sdl_create_buffers())
450507      goto cant_create_buffers;
451508
452   // start playing
453   SDL_PauseAudio(0);
454509   return 0;
455510
456511   // error handling
r907r908
479534
480535static int sdl_create_buffers(void)
481536{
482//   printf("sdl_create_buffers: creating stream buffer of %x bytes\n", stream_buffer_size);
537#if LOG_SOUND
538   fprintf(sound_log, "sdl_create_buffers: creating stream buffer of %d bytes\n", stream_buffer_size);
539#endif
483540   stream_buffer = (INT8 *)malloc(stream_buffer_size);
484541   memset(stream_buffer, 0, stream_buffer_size);
485542   stream_playpos = 0;
486   stream_write_cursor = SDL_XFER_SAMPLES*2;
487543   buf_locked = 0;
488544   return 0;
489545}

Previous 15994 Revisions Next


© 1998-2018 The MESS Team