📄 audio.c
字号:
switch (as->fmt) { case AUD_FMT_S8: AUD_log (NULL, "S8"); break; case AUD_FMT_U8: AUD_log (NULL, "U8"); break; case AUD_FMT_S16: AUD_log (NULL, "S16"); break; case AUD_FMT_U16: AUD_log (NULL, "U16"); break; default: AUD_log (NULL, "invalid(%d)", as->fmt); break; } AUD_log (NULL, "\n");}static int audio_validate_settigs (audsettings_t *as){ int invalid; invalid = as->nchannels != 1 && as->nchannels != 2; switch (as->fmt) { case AUD_FMT_S8: case AUD_FMT_U8: case AUD_FMT_S16: case AUD_FMT_U16: break; default: invalid = 1; break; } invalid |= as->freq <= 0; if (invalid) { return -1; } return 0;}static int audio_pcm_info_eq (struct audio_pcm_info *info, audsettings_t *as){ int bits = 8, sign = 0; switch (as->fmt) { case AUD_FMT_S8: sign = 1; case AUD_FMT_U8: break; case AUD_FMT_S16: sign = 1; case AUD_FMT_U16: bits = 16; break; } return info->freq == as->freq && info->nchannels == as->nchannels && info->sign == sign && info->bits == bits;}void audio_pcm_init_info ( struct audio_pcm_info *info, audsettings_t *as, int swap_endian ){ int bits = 8, sign = 0; switch (as->fmt) { case AUD_FMT_S8: sign = 1; case AUD_FMT_U8: break; case AUD_FMT_S16: sign = 1; case AUD_FMT_U16: bits = 16; break; } info->freq = as->freq; info->bits = bits; info->sign = sign; info->nchannels = as->nchannels; info->shift = (as->nchannels == 2) + (bits == 16); info->align = (1 << info->shift) - 1; info->bytes_per_second = info->freq << info->shift; info->swap_endian = swap_endian;}void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len){ if (!len) { return; } if (info->sign) { memset (buf, len << info->shift, 0x00); } else { if (info->bits == 8) { memset (buf, len << info->shift, 0x80); } else { int i; uint16_t *p = buf; int shift = info->nchannels - 1; short s = INT16_MAX; if (info->swap_endian) { s = bswap16 (s); } for (i = 0; i < len << shift; i++) { p[i] = s; } } }}/* * Hard voice (capture) */static int audio_pcm_hw_find_min_in (HWVoiceIn *hw){ SWVoiceIn *sw; int m = hw->total_samples_captured; for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) { if (sw->active) { m = audio_MIN (m, sw->total_hw_samples_acquired); } } return m;}int audio_pcm_hw_get_live_in (HWVoiceIn *hw){ int live = hw->total_samples_captured - audio_pcm_hw_find_min_in (hw); if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) { dolog ("live=%d hw->samples=%d\n", live, hw->samples); return 0; } return live;}/* * Soft voice (capture) */static int audio_pcm_sw_get_rpos_in (SWVoiceIn *sw){ HWVoiceIn *hw = sw->hw; int live = hw->total_samples_captured - sw->total_hw_samples_acquired; int rpos; if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) { dolog ("live=%d hw->samples=%d\n", live, hw->samples); return 0; } rpos = hw->wpos - live; if (rpos >= 0) { return rpos; } else { return hw->samples + rpos; }}int audio_pcm_sw_read (SWVoiceIn *sw, void *buf, int size){ HWVoiceIn *hw = sw->hw; int samples, live, ret = 0, swlim, isamp, osamp, rpos, total = 0; st_sample_t *src, *dst = sw->buf; rpos = audio_pcm_sw_get_rpos_in (sw) % hw->samples; live = hw->total_samples_captured - sw->total_hw_samples_acquired; if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) { dolog ("live_in=%d hw->samples=%d\n", live, hw->samples); return 0; } samples = size >> sw->info.shift; if (!live) { return 0; } swlim = (live * sw->ratio) >> 32; swlim = audio_MIN (swlim, samples); while (swlim) { src = hw->conv_buf + rpos; isamp = hw->wpos - rpos; /* XXX: <= ? */ if (isamp <= 0) { isamp = hw->samples - rpos; } if (!isamp) { break; } osamp = swlim; if (audio_bug (AUDIO_FUNC, osamp < 0)) { dolog ("osamp=%d\n", osamp); return 0; } st_rate_flow (sw->rate, src, dst, &isamp, &osamp); swlim -= osamp; rpos = (rpos + isamp) % hw->samples; dst += osamp; ret += osamp; total += isamp; } sw->clip (buf, sw->buf, ret); sw->total_hw_samples_acquired += total; return ret << sw->info.shift;}/* * Hard voice (playback) */static int audio_pcm_hw_find_min_out (HWVoiceOut *hw, int *nb_livep){ SWVoiceOut *sw; int m = INT_MAX; int nb_live = 0; for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) { if (sw->active || !sw->empty) { m = audio_MIN (m, sw->total_hw_samples_mixed); nb_live += 1; } } *nb_livep = nb_live; return m;}int audio_pcm_hw_get_live_out2 (HWVoiceOut *hw, int *nb_live){ int smin; smin = audio_pcm_hw_find_min_out (hw, nb_live); if (!*nb_live) { return 0; } else { int live = smin; if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) { dolog ("live=%d hw->samples=%d\n", live, hw->samples); return 0; } return live; }}int audio_pcm_hw_get_live_out (HWVoiceOut *hw){ int nb_live; int live; live = audio_pcm_hw_get_live_out2 (hw, &nb_live); if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) { dolog ("live=%d hw->samples=%d\n", live, hw->samples); return 0; } return live;}/* * Soft voice (playback) */int audio_pcm_sw_write (SWVoiceOut *sw, void *buf, int size){ int hwsamples, samples, isamp, osamp, wpos, live, dead, left, swlim, blck; int ret = 0, pos = 0, total = 0; if (!sw) { return size; } hwsamples = sw->hw->samples; live = sw->total_hw_samples_mixed; if (audio_bug (AUDIO_FUNC, live < 0 || live > hwsamples)){ dolog ("live=%d hw->samples=%d\n", live, hwsamples); return 0; } if (live == hwsamples) { return 0; } wpos = (sw->hw->rpos + live) % hwsamples; samples = size >> sw->info.shift; dead = hwsamples - live; swlim = ((int64_t) dead << 32) / sw->ratio; swlim = audio_MIN (swlim, samples); if (swlim) { sw->conv (sw->buf, buf, swlim, &sw->vol); } while (swlim) { dead = hwsamples - live; left = hwsamples - wpos; blck = audio_MIN (dead, left); if (!blck) { break; } isamp = swlim; osamp = blck; st_rate_flow_mix ( sw->rate, sw->buf + pos, sw->hw->mix_buf + wpos, &isamp, &osamp ); ret += isamp; swlim -= isamp; pos += isamp; live += osamp; wpos = (wpos + osamp) % hwsamples; total += osamp; } sw->total_hw_samples_mixed += total; sw->empty = sw->total_hw_samples_mixed == 0;#ifdef DEBUG_OUT dolog ( "%s: write size %d ret %d total sw %d\n", SW_NAME (sw), size >> sw->info.shift, ret, sw->total_hw_samples_mixed );#endif return ret << sw->info.shift;}#ifdef DEBUG_AUDIOstatic void audio_pcm_print_info (const char *cap, struct audio_pcm_info *info){ dolog ("%s: bits %d, sign %d, freq %d, nchan %d\n", cap, info->bits, info->sign, info->freq, info->nchannels);}#endif#define DAC#include "audio_template.h"#undef DAC#include "audio_template.h"int AUD_write (SWVoiceOut *sw, void *buf, int size){ int bytes; if (!sw) { /* XXX: Consider options */ return size; } if (!sw->hw->enabled) { dolog ("Writing to disabled voice %s\n", SW_NAME (sw)); return 0; } bytes = sw->hw->pcm_ops->write (sw, buf, size); return bytes;}int AUD_read (SWVoiceIn *sw, void *buf, int size){ int bytes; if (!sw) { /* XXX: Consider options */ return size; } if (!sw->hw->enabled) { dolog ("Reading from disabled voice %s\n", SW_NAME (sw)); return 0; } bytes = sw->hw->pcm_ops->read (sw, buf, size); return bytes;}int AUD_get_buffer_size_out (SWVoiceOut *sw){ return sw->hw->samples << sw->hw->info.shift;}void AUD_set_active_out (SWVoiceOut *sw, int on){ HWVoiceOut *hw; if (!sw) { return; } hw = sw->hw; if (sw->active != on) { SWVoiceOut *temp_sw; if (on) { int total; hw->pending_disable = 0; if (!hw->enabled) { hw->enabled = 1; hw->pcm_ops->ctl_out (hw, VOICE_ENABLE); } if (sw->empty) { total = 0; } } else { if (hw->enabled) { int nb_active = 0; for (temp_sw = hw->sw_head.lh_first; temp_sw; temp_sw = temp_sw->entries.le_next) { nb_active += temp_sw->active != 0; } hw->pending_disable = nb_active == 1; } } sw->active = on; }}void AUD_set_active_in (SWVoiceIn *sw, int on){ HWVoiceIn *hw; if (!sw) { return; } hw = sw->hw; if (sw->active != on) { SWVoiceIn *temp_sw; if (on) { if (!hw->enabled) { hw->enabled = 1; hw->pcm_ops->ctl_in (hw, VOICE_ENABLE); } sw->total_hw_samples_acquired = hw->total_samples_captured; } else { if (hw->enabled) { int nb_active = 0; for (temp_sw = hw->sw_head.lh_first; temp_sw; temp_sw = temp_sw->entries.le_next) { nb_active += temp_sw->active != 0; } if (nb_active == 1) { hw->enabled = 0; hw->pcm_ops->ctl_in (hw, VOICE_DISABLE); } } } sw->active = on; }}static int audio_get_avail (SWVoiceIn *sw){ int live;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -