diff -Nru a/include/sound/pcm_oss.h b/include/sound/pcm_oss.h --- a/include/sound/pcm_oss.h Sat Aug 2 12:16:34 2003 +++ b/include/sound/pcm_oss.h Sat Aug 2 12:16:34 2003 @@ -30,7 +30,9 @@ unsigned int disable:1, direct:1, block:1, - nonblock:1; + nonblock:1, + wholefrag:1, + nosilence:1; unsigned int periods; unsigned int period_size; snd_pcm_oss_setup_t *next; diff -Nru a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c --- a/sound/core/oss/pcm_oss.c Sat Aug 2 12:16:35 2003 +++ b/sound/core/oss/pcm_oss.c Sat Aug 2 12:16:35 2003 @@ -22,6 +22,9 @@ #if 0 #define PLUGIN_DEBUG #endif +#if 0 +#define OSS_DEBUG +#endif #include #include @@ -442,7 +445,7 @@ } else { sw_params->start_threshold = runtime->boundary; } - if (atomic_read(&runtime->mmap_count)) + if (atomic_read(&runtime->mmap_count) || substream->stream == SNDRV_PCM_STREAM_CAPTURE) sw_params->stop_threshold = runtime->boundary; else sw_params->stop_threshold = runtime->buffer_size; @@ -451,8 +454,18 @@ sw_params->sleep_min = 0; sw_params->avail_min = runtime->period_size; sw_params->xfer_align = 1; - sw_params->silence_threshold = 0; - sw_params->silence_size = 0; + if (atomic_read(&runtime->mmap_count) || + (substream->oss.setup && substream->oss.setup->nosilence)) { + sw_params->silence_threshold = 0; + sw_params->silence_size = 0; + } else { + snd_pcm_uframes_t frames; + frames = runtime->period_size + 16; + if (frames > runtime->buffer_size) + frames = runtime->buffer_size; + sw_params->silence_threshold = frames; + sw_params->silence_size = frames; + } if ((err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_SW_PARAMS, sw_params)) < 0) { snd_printd("SW_PARAMS failed: %i\n", err); @@ -567,6 +580,31 @@ return 0; } +static int snd_pcm_oss_capture_position_fixup(snd_pcm_substream_t *substream, snd_pcm_sframes_t *delay) +{ + snd_pcm_runtime_t *runtime; + snd_pcm_uframes_t frames; + int err = 0; + + while (1) { + err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, delay); + if (err < 0) + break; + runtime = substream->runtime; + if (*delay <= (snd_pcm_sframes_t)runtime->buffer_size) + break; + /* in case of overrun, skip whole periods like OSS/Linux driver does */ + /* until avail(delay) <= buffer_size */ + frames = (*delay - runtime->buffer_size) + runtime->period_size - 1; + frames /= runtime->period_size; + frames *= runtime->period_size; + err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_FORWARD, &frames); + if (err < 0) + break; + } + return err; +} + snd_pcm_sframes_t snd_pcm_oss_write3(snd_pcm_substream_t *substream, const char *ptr, snd_pcm_uframes_t frames, int in_kernel) { snd_pcm_runtime_t *runtime = substream->runtime; @@ -574,6 +612,12 @@ while (1) { if (runtime->status->state == SNDRV_PCM_STATE_XRUN || runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { +#ifdef OSS_DEBUG + if (runtime->status->state == SNDRV_PCM_STATE_XRUN) + printk("pcm_oss: write: recovering from XRUN\n"); + else + printk("pcm_oss: write: recovering from SUSPEND\n"); +#endif ret = snd_pcm_oss_prepare(substream); if (ret < 0) break; @@ -599,10 +643,17 @@ snd_pcm_sframes_t snd_pcm_oss_read3(snd_pcm_substream_t *substream, char *ptr, snd_pcm_uframes_t frames, int in_kernel) { snd_pcm_runtime_t *runtime = substream->runtime; + snd_pcm_sframes_t delay; int ret; while (1) { if (runtime->status->state == SNDRV_PCM_STATE_XRUN || runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { +#ifdef OSS_DEBUG + if (runtime->status->state == SNDRV_PCM_STATE_XRUN) + printk("pcm_oss: read: recovering from XRUN\n"); + else + printk("pcm_oss: read: recovering from SUSPEND\n"); +#endif ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, 0); if (ret < 0) break; @@ -611,6 +662,9 @@ if (ret < 0) break; } + ret = snd_pcm_oss_capture_position_fixup(substream, &delay); + if (ret < 0) + break; if (in_kernel) { mm_segment_t fs; fs = snd_enter_user(); @@ -640,6 +694,12 @@ while (1) { if (runtime->status->state == SNDRV_PCM_STATE_XRUN || runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { +#ifdef OSS_DEBUG + if (runtime->status->state == SNDRV_PCM_STATE_XRUN) + printk("pcm_oss: writev: recovering from XRUN\n"); + else + printk("pcm_oss: writev: recovering from SUSPEND\n"); +#endif ret = snd_pcm_oss_prepare(substream); if (ret < 0) break; @@ -670,6 +730,12 @@ while (1) { if (runtime->status->state == SNDRV_PCM_STATE_XRUN || runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { +#ifdef OSS_DEBUG + if (runtime->status->state == SNDRV_PCM_STATE_XRUN) + printk("pcm_oss: readv: recovering from XRUN\n"); + else + printk("pcm_oss: readv: recovering from SUSPEND\n"); +#endif ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, 0); if (ret < 0) break; @@ -746,8 +812,9 @@ buf += tmp; bytes -= tmp; xfer += tmp; - if (runtime->oss.buffer_used == runtime->oss.period_bytes) { - tmp = snd_pcm_oss_write2(substream, runtime->oss.buffer, runtime->oss.period_bytes, 1); + if (substream->oss.setup == NULL || !substream->oss.setup->wholefrag || + runtime->oss.buffer_used == runtime->oss.period_bytes) { + tmp = snd_pcm_oss_write2(substream, runtime->oss.buffer, runtime->oss.buffer_used, 1); if (tmp <= 0) return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp; runtime->oss.bytes += tmp; @@ -855,6 +922,22 @@ return 0; } +static int snd_pcm_oss_post(snd_pcm_oss_file_t *pcm_oss_file) +{ + snd_pcm_substream_t *substream; + int err; + + substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; + if (substream != NULL) { + if ((err = snd_pcm_oss_make_ready(substream)) < 0) + return err; + snd_pcm_kernel_playback_ioctl(substream, SNDRV_PCM_IOCTL_START, 0); + } + /* note: all errors from the start action are ignored */ + /* OSS apps do not know, how to handle them */ + return 0; +} + static int snd_pcm_oss_sync(snd_pcm_oss_file_t *pcm_oss_file) { int err = 0; @@ -1188,6 +1271,10 @@ snd_pcm_runtime_t *runtime; snd_pcm_substream_t *psubstream = NULL, *csubstream = NULL; int err, cmd; + +#ifdef OSS_DEBUG + printk("pcm_oss: trigger = 0x%x\n", trigger); +#endif psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; @@ -1288,7 +1375,7 @@ { snd_pcm_substream_t *substream; snd_pcm_runtime_t *runtime; - snd_pcm_status_t status; + snd_pcm_sframes_t delay; struct count_info info; int err; @@ -1306,14 +1393,17 @@ return -EFAULT; return 0; } - memset(&status, 0, sizeof(status)); - err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_STATUS, &status); + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &delay); + } else { + err = snd_pcm_oss_capture_position_fixup(substream, &delay); + } if (err < 0) return err; if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - info.bytes = runtime->oss.bytes - snd_pcm_oss_bytes(substream, runtime->buffer_size - status.avail); + info.bytes = runtime->oss.bytes - snd_pcm_oss_bytes(substream, delay); } else { - info.bytes = runtime->oss.bytes + snd_pcm_oss_bytes(substream, status.avail); + info.bytes = runtime->oss.bytes + snd_pcm_oss_bytes(substream, delay); } info.ptr = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr % runtime->buffer_size); if (atomic_read(&runtime->mmap_count)) { @@ -1326,10 +1416,7 @@ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) snd_pcm_oss_simulate_fill(substream); } else { - if (stream == SNDRV_PCM_STREAM_PLAYBACK) - info.blocks = (runtime->buffer_size - status.avail) / runtime->period_size; - else - info.blocks = status.avail / runtime->period_size; + info.blocks = delay / runtime->period_size; } if (copy_to_user(_info, &info, sizeof(info))) return -EFAULT; @@ -1340,7 +1427,7 @@ { snd_pcm_substream_t *substream; snd_pcm_runtime_t *runtime; - snd_pcm_status_t status; + snd_pcm_sframes_t avail; struct audio_buf_info info; int err; @@ -1357,7 +1444,6 @@ info.fragsize = runtime->oss.period_bytes; info.fragstotal = runtime->periods; - memset(&status, 0, sizeof(status)); if (runtime->oss.prepare) { if (stream == SNDRV_PCM_STREAM_PLAYBACK) { info.bytes = runtime->oss.period_bytes * runtime->periods; @@ -1367,21 +1453,21 @@ info.fragments = 0; } } else { - err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_STATUS, &status); + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &avail); + avail = runtime->buffer_size - avail; + } else { + err = snd_pcm_oss_capture_position_fixup(substream, &avail); + } if (err < 0) return err; - info.bytes = snd_pcm_oss_bytes(substream, status.avail); - info.fragments = status.avail / runtime->period_size; + info.bytes = snd_pcm_oss_bytes(substream, avail); + info.fragments = avail / runtime->period_size; } -#if 0 - /* very experimental stuff to get Quake2 working */ - runtime->oss.period = (info.periods - 1) << 16; - for (tmp = info.fragsize; tmp > 1; tmp >>= 1) - runtime->oss.period++; - runtime->oss.subdivision = 1; /* disable SUBDIVIDE */ +#ifdef OSS_DEBUG + printk("pcm_oss: space: bytes = %i, fragments = %i, fragstotal = %i, fragsize = %i\n", info.bytes, info.fragments, info.fragstotal, info.fragsize); #endif - // printk("space: bytes = %i, periods = %i, fragstotal = %i, fragsize = %i\n", info.bytes, info.periods, info.fragstotal, info.fragsize); if (copy_to_user(_info, &info, sizeof(info))) return -EFAULT; return 0; @@ -1727,6 +1813,9 @@ #endif if (((cmd >> 8) & 0xff) != 'P') return -EINVAL; +#ifdef OSS_DEBUG + printk("pcm_oss: ioctl = 0x%x\n", cmd); +#endif switch (cmd) { case SNDCTL_DSP_RESET: return snd_pcm_oss_reset(pcm_oss_file); @@ -1782,8 +1871,8 @@ case SOUND_PCM_WRITE_FILTER: case SOUND_PCM_READ_FILTER: return -EIO; - case SNDCTL_DSP_POST: /* to do */ - return 0; + case SNDCTL_DSP_POST: + return snd_pcm_oss_post(pcm_oss_file); case SNDCTL_DSP_SUBDIVIDE: if (get_user(res, (int *)arg)) return -EFAULT; @@ -1866,7 +1955,15 @@ substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; if (substream == NULL) return -ENXIO; +#ifndef OSS_DEBUG return snd_pcm_oss_read1(substream, buf, count); +#else + { + ssize_t res = snd_pcm_oss_read1(substream, buf, count); + printk("pcm_oss: read %li bytes (returned %li bytes)\n", (long)count, (long)res); + return res; + } +#endif } static ssize_t snd_pcm_oss_write(struct file *file, const char *buf, size_t count, loff_t *offset) @@ -1882,6 +1979,9 @@ up(&file->f_dentry->d_inode->i_sem); result = snd_pcm_oss_write1(substream, buf, count); down(&file->f_dentry->d_inode->i_sem); +#ifdef OSS_DEBUG + printk("pcm_oss: write %li bytes (wrote %li bytes)\n", (long)count, (long)result); +#endif return result; } @@ -1927,12 +2027,20 @@ } if (csubstream != NULL) { snd_pcm_runtime_t *runtime = csubstream->runtime; + enum sndrv_pcm_state ostate; poll_wait(file, &runtime->sleep, wait); snd_pcm_stream_lock_irq(csubstream); - if (runtime->status->state != SNDRV_PCM_STATE_RUNNING || + if ((ostate = runtime->status->state) != SNDRV_PCM_STATE_RUNNING || snd_pcm_oss_capture_ready(csubstream)) mask |= POLLIN | POLLRDNORM; snd_pcm_stream_unlock_irq(csubstream); + if (ostate != SNDRV_PCM_STATE_RUNNING && runtime->oss.trigger) { + snd_pcm_oss_file_t ofile; + memset(&ofile, 0, sizeof(ofile)); + ofile.streams[SNDRV_PCM_STREAM_CAPTURE] = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; + runtime->oss.trigger = 0; + snd_pcm_oss_set_trigger(&ofile, PCM_ENABLE_INPUT); + } } return mask; @@ -1945,6 +2053,9 @@ snd_pcm_runtime_t *runtime; int err; +#ifdef OSS_DEBUG + printk("pcm_oss: mmap begin\n"); +#endif pcm_oss_file = snd_magic_cast(snd_pcm_oss_file_t, file->private_data, return -ENXIO); switch ((area->vm_flags & (VM_READ | VM_WRITE))) { case VM_READ | VM_WRITE: @@ -1988,6 +2099,9 @@ if (err < 0) return err; runtime->oss.mmap_bytes = area->vm_end - area->vm_start; +#ifdef OSS_DEBUG + printk("pcm_oss: mmap ok, bytes = 0x%x\n", runtime->oss.mmap_bytes); +#endif /* In mmap mode we never stop */ runtime->stop_threshold = runtime->boundary; @@ -2005,14 +2119,16 @@ snd_pcm_oss_setup_t *setup = pstr->oss.setup_list; down(&pstr->oss.setup_mutex); while (setup) { - snd_iprintf(buffer, "%s %u %u%s%s%s%s\n", + snd_iprintf(buffer, "%s %u %u%s%s%s%s%s%s\n", setup->task_name, setup->periods, setup->period_size, setup->disable ? " disable" : "", setup->direct ? " direct" : "", setup->block ? " block" : "", - setup->nonblock ? " non-block" : ""); + setup->nonblock ? " non-block" : "", + setup->wholefrag ? " whole-frag" : "", + setup->nosilence ? " no-silence" : ""); setup = setup->next; } up(&pstr->oss.setup_mutex); @@ -2078,6 +2194,10 @@ template.block = 1; } else if (!strcmp(str, "non-block")) { template.nonblock = 1; + } else if (!strcmp(str, "whole-frag")) { + template.wholefrag = 1; + } else if (!strcmp(str, "no-silence")) { + template.nosilence = 1; } } while (*str); if (setup == NULL) { @@ -2269,3 +2389,24 @@ module_init(alsa_pcm_oss_init) module_exit(alsa_pcm_oss_exit) + +#ifndef MODULE + +/* format is: snd-pcm-oss=dsp_map,adsp_map[,nonblock_open] */ + +static int __init alsa_pcm_oss_setup(char *str) +{ + static unsigned __initdata nr_dev = 0; + + if (nr_dev >= SNDRV_CARDS) + return 0; + (void)(get_option(&str,&dsp_map[nr_dev]) == 2 && + get_option(&str,&adsp_map[nr_dev]) == 2); + (void)(get_option(&str,&nonblock_open) == 2); + nr_dev++; + return 1; +} + +__setup("snd-pcm-oss=", alsa_pcm_oss_setup); + +#endif /* !MODULE */ diff -Nru a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c --- a/sound/core/oss/pcm_plugin.c Sat Aug 2 12:16:31 2003 +++ b/sound/core/oss/pcm_plugin.c Sat Aug 2 12:16:31 2003 @@ -56,6 +56,17 @@ return 0; } +/* + * because some cards might have rates "very close", we ignore + * all "resampling" requests within +-5% + */ +static int rate_match(unsigned int src_rate, unsigned int dst_rate) +{ + unsigned int low = (src_rate * 95) / 100; + unsigned int high = (src_rate * 105) / 100; + return dst_rate >= low && dst_rate <= high; +} + static int snd_pcm_plugin_alloc(snd_pcm_plugin_t *plugin, snd_pcm_uframes_t frames) { snd_pcm_plugin_format_t *format; @@ -80,11 +91,14 @@ plugin->buf = vmalloc(size); plugin->buf_frames = frames; } - if (!plugin->buf) + if (!plugin->buf) { + plugin->buf_frames = 0; return -ENOMEM; + } c = plugin->buf_channels; if (plugin->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) { for (channel = 0; channel < format->channels; channel++, c++) { + c->frames = frames; c->enabled = 1; c->wanted = 0; c->area.addr = plugin->buf; @@ -95,6 +109,7 @@ snd_assert((size % format->channels) == 0,); size /= format->channels; for (channel = 0; channel < format->channels; channel++, c++) { + c->frames = frames; c->enabled = 1; c->wanted = 0; c->area.addr = plugin->buf + (channel * size); @@ -420,7 +435,7 @@ /* Format change (linearization) */ if ((srcformat.format != dstformat.format || - srcformat.rate != dstformat.rate || + !rate_match(srcformat.rate, dstformat.rate) || srcformat.channels != dstformat.channels) && !snd_pcm_format_linear(srcformat.format)) { if (snd_pcm_format_linear(dstformat.format)) @@ -468,7 +483,7 @@ ttable[v * sv + v] = FULL; } tmpformat.channels = dstformat.channels; - if (srcformat.rate == dstformat.rate && + if (rate_match(srcformat.rate, dstformat.rate) && snd_pcm_format_linear(dstformat.format)) tmpformat.format = dstformat.format; err = snd_pcm_plugin_build_route(plug, @@ -490,7 +505,7 @@ } /* rate resampling */ - if (srcformat.rate != dstformat.rate) { + if (!rate_match(srcformat.rate, dstformat.rate)) { tmpformat.rate = dstformat.rate; if (srcformat.channels == dstformat.channels && snd_pcm_format_linear(dstformat.format)) diff -Nru a/sound/core/oss/pcm_plugin.h b/sound/core/oss/pcm_plugin.h --- a/sound/core/oss/pcm_plugin.h Sat Aug 2 12:16:35 2003 +++ b/sound/core/oss/pcm_plugin.h Sat Aug 2 12:16:35 2003 @@ -106,6 +106,7 @@ typedef struct _snd_pcm_plugin_channel { void *aptr; /* pointer to the allocated area */ snd_pcm_channel_area_t area; + snd_pcm_uframes_t frames; /* allocated frames */ unsigned int enabled:1; /* channel need to be processed */ unsigned int wanted:1; /* channel is wanted */ } snd_pcm_plugin_channel_t; diff -Nru a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c --- a/sound/core/pcm_lib.c Sat Aug 2 12:16:31 2003 +++ b/sound/core/pcm_lib.c Sat Aug 2 12:16:31 2003 @@ -60,7 +60,7 @@ return; snd_assert(runtime->silence_filled <= runtime->buffer_size, return); noise_dist = snd_pcm_playback_hw_avail(runtime) + runtime->silence_filled; - if (noise_dist > (snd_pcm_sframes_t) runtime->silence_threshold) + if (noise_dist >= (snd_pcm_sframes_t) runtime->silence_threshold) return; frames = runtime->silence_threshold - noise_dist; if (frames > runtime->silence_size) @@ -84,10 +84,9 @@ if ((snd_pcm_sframes_t)runtime->silence_start < 0) runtime->silence_start += runtime->boundary; } - frames = runtime->buffer_size; + frames = runtime->buffer_size - runtime->silence_filled; } - snd_assert(frames >= runtime->silence_filled, return); - frames -= runtime->silence_filled; + snd_assert(frames <= runtime->buffer_size, return); if (frames == 0) return; ofs = (runtime->silence_start + runtime->silence_filled) % runtime->buffer_size; @@ -1932,7 +1931,7 @@ if (runtime->silence_size >= runtime->boundary) { frames = 1; } else if (runtime->silence_size > 0 && - runtime->silence_filled < runtime->buffer_size) { + runtime->silence_filled < runtime->buffer_size) { snd_pcm_sframes_t noise_dist; noise_dist = snd_pcm_playback_hw_avail(runtime) + runtime->silence_filled; snd_assert(noise_dist <= (snd_pcm_sframes_t)runtime->silence_threshold, ); diff -Nru a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c --- a/sound/core/pcm_memory.c Sat Aug 2 12:16:34 2003 +++ b/sound/core/pcm_memory.c Sat Aug 2 12:16:34 2003 @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -568,3 +569,18 @@ } #endif /* CONFIG_PCI */ + +#ifndef MODULE + +/* format is: snd-pcm=preallocate_dma,maximum_substreams */ + +static int __init alsa_pcm_setup(char *str) +{ + (void)(get_option(&str,&preallocate_dma) == 2 && + get_option(&str,&maximum_substreams) == 2); + return 1; +} + +__setup("snd-pcm=", alsa_pcm_setup); + +#endif /* ifndef MODULE */ diff -Nru a/sound/core/pcm_native.c b/sound/core/pcm_native.c --- a/sound/core/pcm_native.c Sat Aug 2 12:16:31 2003 +++ b/sound/core/pcm_native.c Sat Aug 2 12:16:31 2003 @@ -461,9 +461,15 @@ if (params->xfer_align == 0 || params->xfer_align % runtime->min_align != 0) return -EINVAL; - if ((params->silence_threshold != 0 || params->silence_size < runtime->boundary) && - (params->silence_threshold + params->silence_size > runtime->buffer_size)) - return -EINVAL; + if (params->silence_size >= runtime->boundary) { + if (params->silence_threshold != 0) + return -EINVAL; + } else { + if (params->silence_size > params->silence_threshold) + return -EINVAL; + if (params->silence_threshold > runtime->buffer_size) + return -EINVAL; + } snd_pcm_stream_lock_irq(substream); runtime->tstamp_mode = params->tstamp_mode; runtime->sleep_min = params->sleep_min; diff -Nru a/sound/core/oss/rate.c b/sound/core/oss/rate.c --- a/sound/core/oss/rate.c Sat Aug 2 12:16:32 2003 +++ b/sound/core/oss/rate.c Sat Aug 2 12:16:32 2003 @@ -85,11 +85,7 @@ #undef PUT_S16_LABELS void *get = get_s16_labels[data->get]; void *put = put_s16_labels[data->put]; - void *get_s16_end = 0; signed short sample = 0; -#define GET_S16_END *get_s16_end -#include "plugin_ops.h" -#undef GET_S16_END for (channel = 0; channel < plugin->src_format.channels; channel++) { pos = data->pos; @@ -108,24 +104,16 @@ dst_step = dst_channels[channel].area.step / 8; src_frames1 = src_frames; dst_frames1 = dst_frames; - if (pos & ~R_MASK) { - get_s16_end = &&after_get1; - goto *get; - after_get1: - pos &= R_MASK; - S1 = S2; - S2 = sample; - src += src_step; - src_frames1--; - } while (dst_frames1-- > 0) { if (pos & ~R_MASK) { pos &= R_MASK; S1 = S2; if (src_frames1-- > 0) { - get_s16_end = &&after_get2; goto *get; - after_get2: +#define GET_S16_END after_get +#include "plugin_ops.h" +#undef GET_S16_END + after_get: S2 = sample; src += src_step; } @@ -318,6 +306,8 @@ #endif dst_frames = rate_dst_frames(plugin, frames); + if (dst_frames > dst_channels[0].frames) + dst_frames = dst_channels[0].frames; data = (rate_t *)plugin->extra_data; data->func(plugin, src_channels, dst_channels, frames, dst_frames); return dst_frames;