void snd_pcm_linear_getput(const snd_pcm_channel_area_t *dst_areas, snd_pcm_uframes_t dst_offset, const snd_pcm_channel_area_t *src_areas, snd_pcm_uframes_t src_offset, unsigned int channels, snd_pcm_uframes_t frames, unsigned int get_idx, unsigned int put_idx) { #define CONV24_LABELS #include "plugin_ops.h" #undef CONV24_LABELS void *get = get32_labels[get_idx]; void *put = put32_labels[put_idx]; unsigned int channel; u_int32_t sample = 0; for (channel = 0; channel < channels; ++channel) { const char *src; char *dst; int src_step, dst_step; snd_pcm_uframes_t frames1; const snd_pcm_channel_area_t *src_area = &src_areas[channel]; const snd_pcm_channel_area_t *dst_area = &dst_areas[channel]; src = snd_pcm_channel_area_addr(src_area, src_offset); dst = snd_pcm_channel_area_addr(dst_area, dst_offset); src_step = snd_pcm_channel_area_step(src_area); dst_step = snd_pcm_channel_area_step(dst_area); frames1 = frames; while (frames1-- > 0) { goto *get; #define CONV24_END after #include "plugin_ops.h" #undef CONV24_END after: src += src_step; dst += dst_step; } } }
void snd_pcm_linear_convert(const snd_pcm_channel_area_t *dst_areas, snd_pcm_uframes_t dst_offset, const snd_pcm_channel_area_t *src_areas, snd_pcm_uframes_t src_offset, unsigned int channels, snd_pcm_uframes_t frames, unsigned int convidx) { #define CONV_LABELS #include "plugin_ops.h" #undef CONV_LABELS void *conv = conv_labels[convidx]; unsigned int channel; for (channel = 0; channel < channels; ++channel) { const char *src; char *dst; int src_step, dst_step; snd_pcm_uframes_t frames1; const snd_pcm_channel_area_t *src_area = &src_areas[channel]; const snd_pcm_channel_area_t *dst_area = &dst_areas[channel]; src = snd_pcm_channel_area_addr(src_area, src_offset); dst = snd_pcm_channel_area_addr(dst_area, dst_offset); src_step = snd_pcm_channel_area_step(src_area); dst_step = snd_pcm_channel_area_step(dst_area); frames1 = frames; while (frames1-- > 0) { goto *conv; #define CONV_END after #include "plugin_ops.h" #undef CONV_END after: src += src_step; dst += dst_step; } } }
/* called in pcm lock */ snd_pcm_sframes_t snd_pcm_read_mmap(snd_pcm_t *pcm, snd_pcm_uframes_t offset, snd_pcm_uframes_t size) { snd_pcm_uframes_t xfer = 0; snd_pcm_sframes_t err = 0; if (! size) return 0; while (xfer < size) { snd_pcm_uframes_t frames = size - xfer; snd_pcm_uframes_t cont = pcm->buffer_size - offset; if (cont < frames) frames = cont; switch (pcm->access) { case SND_PCM_ACCESS_MMAP_INTERLEAVED: { const snd_pcm_channel_area_t *a = snd_pcm_mmap_areas(pcm); char *buf = snd_pcm_channel_area_addr(a, offset); snd_pcm_unlock(pcm); /* to avoid deadlock */ err = _snd_pcm_readi(pcm, buf, frames); snd_pcm_lock(pcm); if (err >= 0) frames = err; break; } case SND_PCM_ACCESS_MMAP_NONINTERLEAVED: { snd_pcm_uframes_t channels = pcm->channels; unsigned int c; void *bufs[channels]; const snd_pcm_channel_area_t *areas = snd_pcm_mmap_areas(pcm); for (c = 0; c < channels; ++c) { const snd_pcm_channel_area_t *a = &areas[c]; bufs[c] = snd_pcm_channel_area_addr(a, offset); } snd_pcm_unlock(pcm); /* to avoid deadlock */ err = _snd_pcm_readn(pcm->fast_op_arg, bufs, frames); snd_pcm_lock(pcm); if (err >= 0) frames = err; break; } default: SNDMSG("invalid access type %d", pcm->access); return -EINVAL; } if (err < 0) break; xfer += frames; offset = (offset + frames) % pcm->buffer_size; } if (xfer > 0) return xfer; return err; }
int snd_pcm_area_silence(const snd_pcm_channel_area_t *dst_area, snd_pcm_uframes_t dst_offset, unsigned int samples, snd_pcm_format_t format) { char *dst; unsigned int dst_step; int width; if (!dst_area->addr) return 0; width = snd_pcm_format_physical_width(format); if (width < 8) return area_silence_4bit(dst_area, dst_offset, samples, format); dst = snd_pcm_channel_area_addr(dst_area, dst_offset); if (dst_area->step == (unsigned int) width) { snd_pcm_format_set_silence(format, dst, samples); return 0; } dst_step = dst_area->step / 8; while (samples-- > 0) { snd_pcm_format_set_silence(format, dst, 1); dst += dst_step; } return 0; }
void snd_pcm_lfloat_convert_integer_float(const snd_pcm_channel_area_t *dst_areas, snd_pcm_uframes_t dst_offset, const snd_pcm_channel_area_t *src_areas, snd_pcm_uframes_t src_offset, unsigned int channels, snd_pcm_uframes_t frames, unsigned int get32idx, unsigned int put32floatidx) { #define GET32_LABELS #define PUT32F_LABELS #include "plugin_ops.h" #undef PUT32F_LABELS #undef GET32_LABELS void *get32 = get32_labels[get32idx]; void *put32float = put32float_labels[put32floatidx]; unsigned int channel; for (channel = 0; channel < channels; ++channel) { const char *src; char *dst; int src_step, dst_step; snd_pcm_uframes_t frames1; int32_t sample = 0; snd_tmp_float_t tmp_float; snd_tmp_double_t tmp_double; const snd_pcm_channel_area_t *src_area = &src_areas[channel]; const snd_pcm_channel_area_t *dst_area = &dst_areas[channel]; src = snd_pcm_channel_area_addr(src_area, src_offset); dst = snd_pcm_channel_area_addr(dst_area, dst_offset); src_step = snd_pcm_channel_area_step(src_area); dst_step = snd_pcm_channel_area_step(dst_area); frames1 = frames; while (frames1-- > 0) { goto *get32; #define GET32_END sample_loaded #include "plugin_ops.h" #undef GET32_END sample_loaded: goto *put32float; #define PUT32F_END sample_put #include "plugin_ops.h" #undef PUT32F_END sample_put: src += src_step; dst += dst_step; } } }
static int area_copy_4bit(const snd_pcm_channel_area_t *dst_area, snd_pcm_uframes_t dst_offset, const snd_pcm_channel_area_t *src_area, snd_pcm_uframes_t src_offset, unsigned int samples, snd_pcm_format_t format) { int srcbit = src_area->first % 8; int srcbit_step = src_area->step % 8; int dstbit = dst_area->first % 8; int dstbit_step = dst_area->step % 8; const unsigned char *src = snd_pcm_channel_area_addr(src_area, src_offset); unsigned char *dst = snd_pcm_channel_area_addr(dst_area, dst_offset); int src_step = src_area->step / 8; int dst_step = dst_area->step / 8; while (samples-- > 0) { unsigned char srcval; if (srcbit) srcval = *src & 0x0f; else srcval = *src & 0xf0; if (dstbit) *dst &= 0xf0; else *dst &= 0x0f; *dst |= srcval; src += src_step; srcbit += srcbit_step; if (srcbit == 8) { src++; srcbit = 0; } dst += dst_step; dstbit += dstbit_step; if (dstbit == 8) { dst++; dstbit = 0; } } return 0; }
int snd_pcm_area_copy(const snd_pcm_channel_area_t *dst_area, snd_pcm_uframes_t dst_offset, const snd_pcm_channel_area_t *src_area, snd_pcm_uframes_t src_offset, unsigned int samples, snd_pcm_format_t format) { const char *src; char *dst; int width; int src_step, dst_step; if (!dst_area->addr) return 0; if (dst_area == src_area && dst_offset == src_offset) return 0; if (!src_area->addr) return snd_pcm_area_silence(dst_area, dst_offset, samples, format); width = snd_pcm_format_physical_width(format); if (width < 8) return area_copy_4bit(dst_area, dst_offset, src_area, src_offset, samples, format); src = snd_pcm_channel_area_addr(src_area, src_offset); dst = snd_pcm_channel_area_addr(dst_area, dst_offset); if (src_area->step == (unsigned int) width && dst_area->step == (unsigned int) width) { memcpy(dst, src, samples * width / 8); return 0; } src_step = src_area->step / 8; dst_step = dst_area->step / 8; width /= 8; while (samples-- > 0) { memcpy(dst, src, width); src += src_step; dst += dst_step; } return 0; }
static int area_silence_4bit(const snd_pcm_channel_area_t *dst_area, snd_pcm_uframes_t dst_offset, unsigned int samples, snd_pcm_format_t format) { char *dst = snd_pcm_channel_area_addr(dst_area, dst_offset); int dst_step = dst_area->step / 8; int dstbit = dst_area->first % 8; int dstbit_step = dst_area->step % 8; while (samples-- > 0) { if (dstbit) *dst &= 0xf0; else *dst &= 0x0f; dst += dst_step; dstbit += dstbit_step; if (dstbit == 8) { dst++; dstbit = 0; } } return 0; }