* based on the vplay program by Michael Beck.
*/
-#define BUFFER_SIZE 1000 * 1000
#define WAV_HEADER_LEN 44
#include <sys/time.h> /* gettimeofday */
#include "para.h"
EXIT(E_SAMPLE_FORMAT);
if (snd_pcm_hw_params_set_channels(handle, hwparams, conf.channels_arg) < 0)
EXIT(E_CHANNEL_COUNT);
- if (snd_pcm_hw_params_set_rate_near(handle, hwparams, (unsigned int*) &conf.sample_rate_arg, 0) < 0)
+ if (snd_pcm_hw_params_set_rate_near(handle, hwparams,
+ (unsigned int*) &conf.sample_rate_arg, 0) < 0)
EXIT(E_SET_RATE);
err = snd_pcm_hw_params_get_buffer_time_max(hwparams, &buffer_time, 0);
if (err < 0 || !buffer_time)
EXIT(E_GET_BUFFER_TIME);
- if (buffer_time > 500000)
- buffer_time = 500000;
+ fprintf(stderr, "buffer time: %d\n", buffer_time);
if (snd_pcm_hw_params_set_buffer_time_near(handle, hwparams,
&buffer_time, 0) < 0)
EXIT(E_SET_BUFFER_TIME);
EXIT(E_HW_PARAMS);
snd_pcm_hw_params_get_period_size(hwparams, &chunk_size, 0);
snd_pcm_hw_params_get_buffer_size(hwparams, &buffer_size);
+ fprintf(stderr, "buffer size: %lu, period_size: %lu\n", buffer_size, chunk_size);
if (chunk_size == buffer_size)
EXIT(E_BAD_PERIOD);
snd_pcm_sw_params_current(handle, swparams);
err = snd_pcm_sw_params_get_xfer_align(swparams, &xfer_align);
if (err < 0 || !xfer_align)
EXIT(E_GET_XFER);
- snd_pcm_sw_params_set_sleep_min(handle, swparams, 0);
+// snd_pcm_sw_params_set_sleep_min(handle, swparams, 0);
snd_pcm_sw_params_set_avail_min(handle, swparams, chunk_size);
/* round to closest transfer boundary */
start_threshold = (buffer_size / xfer_align) * xfer_align;
*/
static void do_initial_delay(struct timeval *delay)
{
- fprintf(stderr, "sleeping %lums\n", tv2ms(delay));
+// fprintf(stderr, "sleeping %lums\n", tv2ms(delay));
do
select(1, NULL, NULL, NULL, delay);
while (start_time_in_future(delay));
*/
static void play_pcm(size_t loaded)
{
- size_t chunk_bytes, bufsize, written = 0;
+ size_t chunk_bytes, bufsize, written = 0, prebuf_size;
ssize_t ret;
unsigned char *p;
- int dont_write;
struct timeval delay;
set_alsa_params();
chunk_bytes = chunk_size * bytes_per_frame;
- bufsize = chunk_bytes * 1024;
+ bufsize = (conf.bufsize_arg * 1024 / chunk_bytes) * chunk_bytes;
audiobuf = realloc(audiobuf, bufsize);
if (!audiobuf)
EXIT(E_MEM);
+ prebuf_size = conf.prebuffer_arg * bufsize / 100;
again:
- dont_write = 0;
- if (!written && start_time)
- dont_write = start_time_in_future(&delay);
- if (!dont_write) {
- p = audiobuf;
- while (loaded >= chunk_bytes) {
- ret = pcm_write(p, chunk_size) * bytes_per_frame;
- p += ret;
- written += ret;
- loaded -= ret;
- }
- if (loaded && p != audiobuf) {
- fprintf(stderr, "memcpy: %d\n", loaded);
- memcpy(audiobuf, p, loaded);
+ if (!written) {
+ if (loaded < prebuf_size)
+ goto read;
+ if (start_time && start_time_in_future(&delay)) {
+ do_initial_delay(&delay);
+ start_time = NULL;
}
}
- if (dont_write && loaded >= bufsize) {
- do_initial_delay(&delay);
- start_time = NULL;
- goto again;
+ p = audiobuf;
+ while (loaded >= chunk_bytes) {
+// fprintf(stderr, "write (loaded = %d)\n", loaded);
+ ret = pcm_write(p, chunk_size) * bytes_per_frame;
+ p += ret;
+ written += ret;
+ loaded -= ret;
+ }
+ if (loaded && p != audiobuf) {
+// fprintf(stderr, "memcpy: %d@%d\n", loaded, p - audiobuf);
+ memcpy(audiobuf, p, loaded);
}
- ret = read(STDIN_FILENO, audiobuf, bufsize - loaded);
+read:
+ ret = read(STDIN_FILENO, audiobuf + loaded, bufsize - loaded);
if (ret < 0)
EXIT(E_READ);
if (ret) {