Advertisement
Guest User

005-sdl-alsa-buffer.patch

a guest
Mar 4th, 2013
208
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 10.64 KB | None | 0 0
  1. diff -rupN SDL.orig/src/audio/alsa/SDL_alsa_audio.c SDL-1.2.14/src/audio/alsa/SDL_alsa_audio.c
  2. --- SDL.orig/src/audio/alsa/SDL_alsa_audio.c    2013-02-27 08:25:35.000000000 -0500
  3. +++ SDL-1.2.14/src/audio/alsa/SDL_alsa_audio.c  2013-02-27 10:50:04.000000000 -0500
  4. @@ -43,6 +43,13 @@
  5.  /* The tag name used by ALSA audio */
  6.  #define DRIVER_NAME         "alsa"
  7.  
  8. +#if 1
  9. +/* Both aplay and mpg123 seem to go for a 0.5s buffer */
  10. +static int BUFFER_LENGTH = 1000;               /* in millisecs */
  11. +static int PLAY_START_THRESH = (1000/2);           /* in millisecs */
  12. +static int PERIOD_LENGTH = 1024;               /* in frames */
  13. +#endif
  14. +
  15.  /* Audio driver functions */
  16.  static int ALSA_OpenAudio(_THIS, SDL_AudioSpec *spec);
  17.  static void ALSA_WaitAudio(_THIS);
  18. @@ -308,6 +315,7 @@ static void ALSA_PlayAudio(_THIS)
  19.     snd_pcm_uframes_t frames_left;
  20.     const Uint8 *sample_buf = (const Uint8 *) mixbuf;
  21.     const int frame_size = (((int) (this->spec.format & 0xFF)) / 8) * this->spec.channels;
  22. +        int frames;
  23.  
  24.     swizzle_alsa_channels(this);
  25.  
  26. @@ -317,22 +325,35 @@ static void ALSA_PlayAudio(_THIS)
  27.         /* This works, but needs more testing before going live */
  28.         /*SDL_NAME(snd_pcm_wait)(pcm_handle, -1);*/
  29.  
  30. -       status = SDL_NAME(snd_pcm_writei)(pcm_handle, sample_buf, frames_left);
  31. +       frames = frames_left;
  32. +       status = SDL_NAME(snd_pcm_writei)(pcm_handle, sample_buf, frames);
  33.         if ( status < 0 ) {
  34.             if ( status == -EAGAIN ) {
  35.                 /* Apparently snd_pcm_recover() doesn't handle this case - does it assume snd_pcm_wait() above? */
  36.                 SDL_Delay(1);
  37.                 continue;
  38.             }
  39. +#if 0
  40. +           if ( status == -EPIPE ) {
  41. +               /* EPIPE means underrun */
  42. +                                PRINTF("SDL_DBG %s Underrun.\n", __FUNCTION__);
  43. +           }
  44. +           else
  45. +               PRINTF("SDL_DBG %s pcm_recover(%d).\n", __FUNCTION__, status);
  46. +#endif
  47.             status = SDL_NAME(snd_pcm_recover)(pcm_handle, status, 0);
  48.             if ( status < 0 ) {
  49.                 /* Hmm, not much we can do - abort */
  50.                 fprintf(stderr, "ALSA write failed (unrecoverable): %s\n", SDL_NAME(snd_strerror)(status));
  51. -               this->enabled = 0;
  52. +               this->enabled = 0;        
  53.                 return;
  54.             }
  55.             continue;
  56.         }
  57. +#if 0
  58. +                else if (status != frames)
  59. +                    PRINTF("SDL_DBG %s short write %d frames.\n", __FUNCTION__, status);
  60. +#endif
  61.         sample_buf += status * frame_size;
  62.         frames_left -= status;
  63.     }
  64. @@ -360,6 +381,8 @@ static int ALSA_finalize_hardware(_THIS,
  65.  {
  66.     int status;
  67.     snd_pcm_uframes_t bufsize;
  68. +   snd_pcm_uframes_t persize = 0;
  69. +   unsigned int periods = 0;
  70.  
  71.     /* "set" the hardware with the desired parameters */
  72.     status = SDL_NAME(snd_pcm_hw_params)(pcm_handle, hwparams);
  73. @@ -372,23 +395,39 @@ static int ALSA_finalize_hardware(_THIS,
  74.     if ( status < 0 ) {
  75.         return(-1);
  76.     }
  77. -   if ( !override && bufsize != spec->samples * 2 ) {
  78. +#if 0
  79. +        if ( !override && bufsize != spec->samples * 2 ) {
  80.         return(-1);
  81.     }
  82.  
  83.     /* FIXME: Is this safe to do? */
  84.     spec->samples = bufsize / 2;
  85. +#else
  86. +   /* For ZIPIT test 16k buffer with various period sizes */
  87. +   status = SDL_NAME(snd_pcm_hw_params_get_period_size)(hwparams, &persize, NULL);
  88. +   if ( status < 0 ) {
  89. +       return(-1);
  90. +   }
  91. +   if ( !override && persize != spec->samples ) {
  92. +       return(-1);
  93. +   }
  94. +   spec->samples = persize;
  95. +        periodsize = 32; /* Loop write size.  Try smaller than persize; */
  96. +#endif
  97.  
  98.     /* This is useful for debugging */
  99.     if ( getenv("SDL_AUDIO_ALSA_DEBUG") ) {
  100. -       snd_pcm_uframes_t persize = 0;
  101. -       unsigned int periods = 0;
  102. -
  103.         SDL_NAME(snd_pcm_hw_params_get_period_size)(hwparams, &persize, NULL);
  104.         SDL_NAME(snd_pcm_hw_params_get_periods)(hwparams, &periods, NULL);
  105. +       periodsize = persize;
  106.  
  107.         fprintf(stderr, "ALSA: period size = %ld, periods = %u, buffer size = %lu\n", persize, periods, bufsize);
  108.     }
  109. +        else { /* ZIPIT */
  110. +       SDL_NAME(snd_pcm_hw_params_get_periods)(hwparams, &periods, NULL);
  111. +                /* PRINTF("SDL_DBG: period size = %ld, periods = %u, buffer size = %lu\n", persize, periods, bufsize); */
  112. +        }
  113. +
  114.     return(0);
  115.  }
  116.  
  117. @@ -415,6 +454,7 @@ static int ALSA_set_period_size(_THIS, S
  118.     }
  119.  
  120.     frames = spec->samples;
  121. +#if 0
  122.     status = SDL_NAME(snd_pcm_hw_params_set_period_size_near)(pcm_handle, hwparams, &frames, NULL);
  123.     if ( status < 0 ) {
  124.         return(-1);
  125. @@ -425,6 +465,26 @@ static int ALSA_set_period_size(_THIS, S
  126.     if ( status < 0 ) {
  127.         return(-1);
  128.     }
  129. +#else
  130. +   /* For ZIPIT test 16k buffer with various period sizes */
  131. +   /* Lets try 1024 instead of spec->samples from SDL. */
  132. +   frames = 1024;
  133. +
  134. +   if (frames > (16384 / 2))
  135. +     periods = 2;
  136. +   else
  137. +     periods = 16384 / frames;
  138. +
  139. +   status = SDL_NAME(snd_pcm_hw_params_set_period_size_near)(pcm_handle, hwparams, &frames, NULL);
  140. +   if ( status < 0 ) {
  141. +       return(-1);
  142. +   }
  143. +
  144. +   status = SDL_NAME(snd_pcm_hw_params_set_periods_near)(pcm_handle, hwparams, &periods, NULL);
  145. +   if ( status < 0 ) {
  146. +       return(-1);
  147. +   }
  148. +#endif
  149.  
  150.     return ALSA_finalize_hardware(this, spec, hwparams, override);
  151.  }
  152. @@ -449,8 +509,12 @@ static int ALSA_set_buffer_size(_THIS, S
  153.             }
  154.         }
  155.     }
  156. -
  157. +#if 0
  158.     frames = spec->samples * 2;
  159. +#else
  160. +   /* For ZIPIT test 16k buffer with various period sizes */
  161. +   frames = 16384;
  162. +#endif
  163.     status = SDL_NAME(snd_pcm_hw_params_set_buffer_size_near)(pcm_handle, hwparams, &frames);
  164.     if ( status < 0 ) {
  165.         return(-1);
  166. @@ -467,6 +531,11 @@ static int ALSA_OpenAudio(_THIS, SDL_Aud
  167.     snd_pcm_format_t     format;
  168.     unsigned int         rate;
  169.     unsigned int         channels;
  170. +        const char *         env;
  171. +   snd_pcm_uframes_t    buffer_size;
  172. +   snd_pcm_uframes_t    period_size;
  173. +   snd_pcm_uframes_t    start_thresh = 1;
  174. +   snd_pcm_uframes_t    frames;
  175.     Uint16               test_format;
  176.  
  177.     /* Open the audio device */
  178. @@ -560,6 +629,7 @@ static int ALSA_OpenAudio(_THIS, SDL_Aud
  179.     }
  180.     spec->freq = rate;
  181.  
  182. +#if 0
  183.     /* Set the buffer size, in samples */
  184.     if ( ALSA_set_period_size(this, spec, hwparams, 0) < 0 &&
  185.          ALSA_set_buffer_size(this, spec, hwparams, 0) < 0 ) {
  186. @@ -570,6 +640,85 @@ static int ALSA_OpenAudio(_THIS, SDL_Aud
  187.             return(-1);
  188.         }
  189.     }
  190. +#else
  191. +   frames = spec->samples * 2;
  192. +
  193. +   /* On ZIPIT IZ2S just go for 1 sec buffer and 1024 periods. */
  194. +        env = getenv("SDL_AUDIO_ALSA_SET_BUFFER_SIZE");
  195. +        if ( env ) {
  196. +       status = SDL_atoi(env);
  197. +                if ( status > 1 )
  198. +                    BUFFER_LENGTH = status;
  199. +        }
  200. +   frames = buffer_size = rate * BUFFER_LENGTH / 1000;
  201. +   status = SDL_NAME(snd_pcm_hw_params_set_buffer_size_near)(pcm_handle, hwparams, &frames);
  202. +   if ( status < 0 ) {
  203. +       SDL_SetError("Couldn't set buffer size: %s", SDL_NAME(snd_strerror)(status));
  204. +       ALSA_CloseAudio(this);
  205. +       return(-1);
  206. +   }
  207. +
  208. +        /* Since we can override in env, lets start with the SDL period_size. */
  209. +        PERIOD_LENGTH = spec->samples;
  210. +
  211. +        env = getenv("SDL_AUDIO_ALSA_SET_PERIOD_SIZE");
  212. +        if ( env ) {
  213. +       status = SDL_atoi(env);
  214. +                if ( status > 1 )
  215. +                    PERIOD_LENGTH = status;
  216. +        }
  217. +        frames = period_size = PERIOD_LENGTH;
  218. +   if (snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &frames, NULL) < 0) {
  219. +       SDL_SetError("Couldn't set period size: %s", SDL_NAME(snd_strerror)(status));
  220. +       ALSA_CloseAudio(this);
  221. +       return(-1);
  222. +   }
  223. +
  224. +   /* "set" the hardware with the desired parameters */
  225. +   status = SDL_NAME(snd_pcm_hw_params)(pcm_handle, hwparams);
  226. +   if ( status < 0 ) {
  227. +       SDL_SetError("Couldn't set hardware audio parameters: %s", SDL_NAME(snd_strerror)(status));
  228. +       ALSA_CloseAudio(this);
  229. +       return(-1);
  230. +   }
  231. +
  232. +        env = getenv("SDL_AUDIO_ALSA_SET_START_THRESH");
  233. +        if ( env ) {
  234. +       status = SDL_atoi(env);
  235. +                if ( status >= 0 )
  236. +                    PLAY_START_THRESH = status;
  237. +        }
  238. +        start_thresh = rate * PLAY_START_THRESH / 1000;
  239. +
  240. +   /* Get samples for the actual buffer size */
  241. +   status = SDL_NAME(snd_pcm_hw_params_get_buffer_size)(hwparams, &buffer_size);
  242. +   if ( status < 0 ) {
  243. +       SDL_SetError("Couldn't set buffer size: %s", SDL_NAME(snd_strerror)(status));
  244. +       ALSA_CloseAudio(this);
  245. +       return(-1);
  246. +   }
  247. +   status = SDL_NAME(snd_pcm_hw_params_get_period_size)(hwparams, &period_size, NULL);
  248. +   if ( status < 0 ) {
  249. +       SDL_SetError("Couldn't get period size: %s", SDL_NAME(snd_strerror)(status));
  250. +       ALSA_CloseAudio(this);
  251. +       return(-1);
  252. +   }
  253. +
  254. +        if (PLAY_START_THRESH <= 1)
  255. +            start_thresh = 1; /* start playing after the first write */
  256. +        else /* start playing after a few periods to calm down rockbox outta the gate */
  257. +   {
  258. +            if (start_thresh > buffer_size)
  259. +                frames = buffer_size;
  260. +            else for (frames = 0; frames < start_thresh; frames+=period_size);
  261. +            if (frames < 1)
  262. +           frames = period_size*2;
  263. +            start_thresh = frames;
  264. +        }
  265. +
  266. +        /* Tell the SDL client what we really got for period_size. */
  267. +   spec->samples = period_size;
  268. +#endif
  269.  
  270.     /* Set the software parameters */
  271.     snd_pcm_sw_params_alloca(&swparams);
  272. @@ -579,12 +728,22 @@ static int ALSA_OpenAudio(_THIS, SDL_Aud
  273.         ALSA_CloseAudio(this);
  274.         return(-1);
  275.     }
  276. -   status = SDL_NAME(snd_pcm_sw_params_set_start_threshold)(pcm_handle, swparams, 1);
  277. +
  278. +   /* Start playing after so many frames. */        
  279. +        frames = start_thresh;
  280. +   status = SDL_NAME(snd_pcm_sw_params_set_start_threshold)(pcm_handle, swparams, frames);
  281.     if ( status < 0 ) {
  282.         SDL_SetError("Couldn't set start threshold: %s", SDL_NAME(snd_strerror)(status));
  283.         ALSA_CloseAudio(this);
  284.         return(-1);
  285.     }
  286. +   /* wake up on every interrupt */
  287. +   status = snd_pcm_sw_params_set_avail_min(pcm_handle, swparams, 1);
  288. +   if ( status < 0 ) {
  289. +       SDL_SetError("Couldn't set min available: %s", SDL_NAME(snd_strerror)(status));
  290. +       ALSA_CloseAudio(this);
  291. +       return -1;
  292. +   }
  293.     status = SDL_NAME(snd_pcm_sw_params)(pcm_handle, swparams);
  294.     if ( status < 0 ) {
  295.         SDL_SetError("Couldn't set software audio parameters: %s", SDL_NAME(snd_strerror)(status));
  296. diff -rupN SDL.orig/src/audio/alsa/SDL_alsa_audio.h SDL-1.2.14/src/audio/alsa/SDL_alsa_audio.h
  297. --- SDL.orig/src/audio/alsa/SDL_alsa_audio.h    2013-02-27 08:25:35.000000000 -0500
  298. +++ SDL-1.2.14/src/audio/alsa/SDL_alsa_audio.h  2013-02-27 09:48:14.000000000 -0500
  299. @@ -35,6 +35,9 @@ struct SDL_PrivateAudioData {
  300.     /* The audio device handle */
  301.     snd_pcm_t *pcm_handle;
  302.  
  303. +        /* periods */
  304. +        snd_pcm_uframes_t periodsize;
  305. +
  306.     /* Raw mixing buffer */
  307.     Uint8 *mixbuf;
  308.     int    mixlen;
  309. @@ -44,5 +47,6 @@ struct SDL_PrivateAudioData {
  310.  #define pcm_handle     (this->hidden->pcm_handle)
  311.  #define mixbuf         (this->hidden->mixbuf)
  312.  #define mixlen         (this->hidden->mixlen)
  313. +#define periodsize     (this->hidden->periodsize)
  314.  
  315.  #endif /* _ALSA_PCM_audio_h */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement