typedef struct {
snd_pcm_t *pcm;
size_t frame_bytes;
- snd_pcm_uframes_t period_size;
- unsigned int periods;
- snd_pcm_uframes_t buffer_size;
- size_t bytes;
- snd_pcm_uframes_t boundary;
- snd_pcm_uframes_t old_hw_ptr;
+ struct {
+ snd_pcm_uframes_t period_size;
+ snd_pcm_uframes_t buffer_size;
+ snd_pcm_uframes_t boundary;
+ snd_pcm_uframes_t old_hw_ptr;
+ size_t mmap_buffer_bytes;
+ size_t mmap_period_bytes;
+ } alsa;
+ struct {
+ snd_pcm_uframes_t period_size;
+ unsigned int periods;
+ snd_pcm_uframes_t buffer_size;
+ size_t bytes;
+ } oss;
unsigned int stopped:1;
void *mmap_buffer;
size_t mmap_bytes;
- size_t mmap_buffer_bytes;
- size_t mmap_period_bytes;
snd_pcm_channel_area_t *mmap_areas;
snd_pcm_uframes_t mmap_advance;
} oss_dsp_stream_t;
#define OSS_DEVICE_AMIDI 13
#define OSS_DEVICE_ADMMIDI 14
+static unsigned int ld2(u_int32_t v)
+{
+ unsigned r = 0;
+
+ if (v >= 0x10000) {
+ v >>= 16;
+ r += 16;
+ }
+ if (v >= 0x100) {
+ v >>= 8;
+ r += 8;
+ }
+ if (v >= 0x10) {
+ v >>= 4;
+ r += 4;
+ }
+ if (v >= 4) {
+ v >>= 2;
+ r += 2;
+ }
+ if (v >= 2)
+ r++;
+ return r;
+}
+
static snd_pcm_format_t oss_format_to_alsa(int format)
{
switch (format) {
err = snd_pcm_hw_params_set_access_mask(pcm, hw, mask);
if (err < 0)
return err;
- err = snd_pcm_hw_params_set_period_size(pcm, hw, str->mmap_period_bytes / str->frame_bytes, 0);
+ err = snd_pcm_hw_params_set_period_size(pcm, hw, str->alsa.mmap_period_bytes / str->frame_bytes, 0);
if (err < 0)
return err;
- err = snd_pcm_hw_params_set_buffer_size(pcm, hw, str->mmap_buffer_bytes / str->frame_bytes);
+ err = snd_pcm_hw_params_set_buffer_size(pcm, hw, str->alsa.mmap_buffer_bytes / str->frame_bytes);
if (err < 0)
return err;
err = snd_pcm_hw_params_set_access(pcm, hw, SND_PCM_ACCESS_MMAP_INTERLEAVED);
s = (1 << dsp->fragshift) / str->frame_bytes;
err = snd_pcm_hw_params_set_period_size_near(pcm, hw, &s, 0);
}
- fprintf(stderr, "set period size = %li, err = %i\n", s, err);
} else {
snd_pcm_uframes_t s = 16, old_s;
while (s * 2 < dsp->rate / 2)
if (err < 0)
return err;
}
-
err = snd_pcm_hw_params(pcm, hw);
+ if (err < 0)
+ return err;
#if 0
if (debug)
snd_pcm_dump_setup(pcm, stderr);
#endif
- err = snd_pcm_hw_params_get_rate(hw, &dsp->rate, 0);
if (err < 0)
return err;
dsp->oss_format = alsa_format_to_oss(dsp->format);
- err = snd_pcm_hw_params_get_period_size(hw, &str->period_size, 0);
+ err = snd_pcm_hw_params_get_period_size(hw, &str->alsa.period_size, 0);
if (err < 0)
return err;
- err = snd_pcm_hw_params_get_periods(hw, &str->periods, 0);
+ err = snd_pcm_hw_params_get_buffer_size(hw, &str->alsa.buffer_size);
if (err < 0)
return err;
- str->buffer_size = str->periods * str->period_size;
- free(str->mmap_areas);
- str->mmap_areas = 0;
+ str->oss.buffer_size = 1 << ld2(str->alsa.buffer_size);
+ if (str->oss.buffer_size < str->alsa.buffer_size)
+ str->oss.buffer_size *= 2;
+ str->oss.period_size = 1 << ld2(str->alsa.period_size);
+ if (str->oss.period_size < str->alsa.period_size)
+ str->oss.period_size *= 2;
+ str->oss.periods = str->oss.buffer_size / str->oss.period_size;
+ if (str->mmap_areas)
+ free(str->mmap_areas);
+ str->mmap_areas = NULL;
if (str->mmap_buffer) {
unsigned int c;
snd_pcm_channel_area_t *a;
snd_pcm_sw_params_current(pcm, sw);
snd_pcm_sw_params_set_xfer_align(pcm, sw, 1);
snd_pcm_sw_params_set_start_threshold(pcm, sw,
- str->stopped ? str->buffer_size + 1 : 1);
+ str->stopped ? str->alsa.buffer_size + 1 :
+ str->alsa.period_size);
#if 1
snd_pcm_sw_params_set_stop_threshold(pcm, sw,
str->mmap_buffer ? LONG_MAX :
- str->buffer_size);
+ str->alsa.buffer_size);
#else
snd_pcm_sw_params_set_stop_threshold(pcm, sw,
LONG_MAX);
snd_pcm_sw_params_set_silence_threshold(pcm, sw,
- str->period_size);
+ str->alsa.period_size);
snd_pcm_sw_params_set_silence_size(pcm, sw,
- str->period_size);
+ str->alsa.period_size);
#endif
err = snd_pcm_sw_params(pcm, sw);
if (err < 0)
return err;
- str->boundary = _snd_pcm_boundary(pcm);
+ str->alsa.boundary = _snd_pcm_boundary(pcm);
}
return 0;
}
goto _end;
}
result *= str->frame_bytes;
- str->bytes += result;
+ str->oss.bytes += result;
_end:
DEBUG("write(%d, %p, %ld) -> %ld", fd, buf, (long)n, (long)result);
if (result < 0)
goto _end;
}
result *= str->frame_bytes;
- str->bytes += result;
+ str->oss.bytes += result;
_end:
DEBUG("read(%d, %p, %ld) -> %ld", fd, buf, (long)n, (long)result);
if (result < 0)
// fprintf(stderr, "mmap_advance=%ld\n", str->mmap_advance);
}
#if USE_REWIND
- err = snd_pcm_rewind(pcm, str->buffer_size);
+ err = snd_pcm_rewind(pcm, str->alsa.buffer_size);
if (err < 0)
return;
size = str->mmap_advance;
err = snd_pcm_prepare(pcm);
if (err < 0)
result = err;
- str->bytes = 0;
+ str->oss.bytes = 0;
}
err = result;
break;
if (!str->pcm)
str = &dsp->streams[SND_PCM_STREAM_CAPTURE];
pcm = str->pcm;
- *(int *) arg = str->period_size * str->frame_bytes;
+ *(int *) arg = str->oss.period_size * str->frame_bytes;
DEBUG("SNDCTL_DSP_GETBLKSIZE, %p) -> [%d]\n", arg, *(int *)arg);
break;
case SNDCTL_DSP_POST:
if (str->mmap_buffer) {
const snd_pcm_channel_area_t *areas;
snd_pcm_uframes_t offset;
- snd_pcm_uframes_t size = str->buffer_size;
+ snd_pcm_uframes_t size = str->alsa.buffer_size;
snd_pcm_mmap_begin(pcm, &areas, &offset, &size);
snd_pcm_areas_copy(areas, 0, str->mmap_areas, 0,
dsp->channels, size,
avail = snd_pcm_avail_update(pcm);
if (avail < 0)
avail = 0;
- if ((snd_pcm_uframes_t)avail > str->buffer_size)
- avail = str->buffer_size;
- info->fragsize = str->period_size * str->frame_bytes;
- info->fragstotal = str->periods;
+ if ((snd_pcm_uframes_t)avail > str->oss.buffer_size)
+ avail = str->oss.buffer_size;
+ info->fragsize = str->oss.period_size * str->frame_bytes;
+ info->fragstotal = str->oss.periods;
info->bytes = avail * str->frame_bytes;
- info->fragments = avail / str->period_size;
+ info->fragments = avail / str->oss.period_size;
DEBUG("SNDCTL_DSP_GETISPACE, %p) -> {%d, %d, %d, %d}\n", arg,
info->fragments,
info->fragstotal,
oss_dsp_mmap_update(dsp, SND_PCM_STREAM_PLAYBACK, delay);
}
avail = snd_pcm_avail_update(pcm);
- if (avail < 0 || (snd_pcm_uframes_t)avail > str->buffer_size)
- avail = str->buffer_size;
- info->fragsize = str->period_size * str->frame_bytes;
- info->fragstotal = str->periods;
+ if (avail < 0 || (snd_pcm_uframes_t)avail > str->oss.buffer_size)
+ avail = str->oss.buffer_size;
+ info->fragsize = str->oss.period_size * str->frame_bytes;
+ info->fragstotal = str->oss.periods;
info->bytes = avail * str->frame_bytes;
- info->fragments = avail / str->period_size;
+ info->fragments = avail / str->oss.period_size;
DEBUG("SNDCTL_DSP_GETOSPACE, %p) -> {%d %d %d %d}\n", arg,
info->fragments,
info->fragstotal,
hw_ptr = _snd_pcm_mmap_hw_ptr(pcm);
info->bytes = hw_ptr;
info->bytes *= str->frame_bytes;
- info->ptr = hw_ptr % str->buffer_size;
+ info->ptr = hw_ptr % str->oss.buffer_size;
info->ptr *= str->frame_bytes;
if (str->mmap_buffer) {
- ssize_t n = (hw_ptr / str->period_size) - (str->old_hw_ptr / str->period_size);
+ ssize_t n = (hw_ptr / str->oss.period_size) - (str->alsa.old_hw_ptr / str->oss.period_size);
if (n < 0)
- n += str->boundary / str->period_size;
+ n += str->alsa.boundary / str->oss.period_size;
info->blocks = n;
- str->old_hw_ptr = hw_ptr;
+ str->alsa.old_hw_ptr = hw_ptr;
} else
- info->blocks = delay / str->period_size;
+ info->blocks = delay / str->oss.period_size;
DEBUG("SNDCTL_DSP_GETIPTR, %p) -> {%d %d %d}\n", arg,
info->bytes,
info->blocks,
hw_ptr = _snd_pcm_mmap_hw_ptr(pcm);
info->bytes = hw_ptr;
info->bytes *= str->frame_bytes;
- info->ptr = hw_ptr % str->buffer_size;
+ info->ptr = hw_ptr % str->oss.buffer_size;
info->ptr *= str->frame_bytes;
if (str->mmap_buffer) {
- ssize_t n = (hw_ptr / str->period_size) - (str->old_hw_ptr / str->period_size);
+ ssize_t n = (hw_ptr / str->oss.period_size) - (str->alsa.old_hw_ptr / str->oss.period_size);
if (n < 0)
- n += str->boundary / str->period_size;
+ n += str->alsa.boundary / str->oss.period_size;
info->blocks = n;
- str->old_hw_ptr = hw_ptr;
+ str->alsa.old_hw_ptr = hw_ptr;
} else
- info->blocks = delay / str->period_size;
+ info->blocks = delay / str->oss.period_size;
DEBUG("SNDCTL_DSP_GETOPTR, %p) -> {%d %d %d}\n", arg,
info->bytes,
info->blocks,
}
str->mmap_buffer = result;
str->mmap_bytes = len;
- str->mmap_period_bytes = str->period_size * str->frame_bytes;
- str->mmap_buffer_bytes = str->buffer_size * str->frame_bytes;
+ str->alsa.mmap_period_bytes = str->oss.period_size * str->frame_bytes;
+ str->alsa.mmap_buffer_bytes = str->oss.buffer_size * str->frame_bytes;
err = oss_dsp_params(dsp);
if (err < 0) {
free(result);