📄 ossaudio.c
字号:
} if (oss->mmapped) { oss->old_optr = cntinfo.ptr; } hw->rpos = rpos; return decr;}static void oss_fini_out (HWVoiceOut *hw){ int err; OSSVoiceOut *oss = (OSSVoiceOut *) hw; ldebug ("oss_fini\n"); oss_anal_close (&oss->fd); if (oss->pcm_buf) { if (oss->mmapped) { err = munmap (oss->pcm_buf, hw->samples << hw->info.shift); if (err) { oss_logerr (errno, "Failed to unmap buffer %p, size %d\n", oss->pcm_buf, hw->samples << hw->info.shift); } } else { qemu_free (oss->pcm_buf); } oss->pcm_buf = NULL; }}static int oss_init_out (HWVoiceOut *hw, audsettings_t *as){ OSSVoiceOut *oss = (OSSVoiceOut *) hw; struct oss_params req, obt; int endianness; int err; int fd; audfmt_e effective_fmt; audsettings_t obt_as; oss->fd = -1; req.fmt = aud_to_ossfmt (as->fmt); req.freq = as->freq; req.nchannels = as->nchannels; req.fragsize = conf.fragsize; req.nfrags = conf.nfrags; if (oss_open (0, &req, &obt, &fd)) { return -1; } err = oss_to_audfmt (obt.fmt, &effective_fmt, &endianness); if (err) { oss_anal_close (&fd); return -1; } obt_as.freq = obt.freq; obt_as.nchannels = obt.nchannels; obt_as.fmt = effective_fmt; audio_pcm_init_info ( &hw->info, &obt_as, audio_need_to_swap_endian (endianness) ); oss->nfrags = obt.nfrags; oss->fragsize = obt.fragsize; if (obt.nfrags * obt.fragsize & hw->info.align) { dolog ("warning: Misaligned DAC buffer, size %d, alignment %d\n", obt.nfrags * obt.fragsize, hw->info.align + 1); } hw->samples = (obt.nfrags * obt.fragsize) >> hw->info.shift; oss->mmapped = 0; if (conf.try_mmap) { oss->pcm_buf = mmap ( 0, hw->samples << hw->info.shift, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 ); if (oss->pcm_buf == MAP_FAILED) { oss_logerr (errno, "Failed to map %d bytes of DAC\n", hw->samples << hw->info.shift); } else { int err; int trig = 0; if (ioctl (fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) { oss_logerr (errno, "SNDCTL_DSP_SETTRIGGER 0 failed\n"); } else { trig = PCM_ENABLE_OUTPUT; if (ioctl (fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) { oss_logerr ( errno, "SNDCTL_DSP_SETTRIGGER PCM_ENABLE_OUTPUT failed\n" ); } else { oss->mmapped = 1; } } if (!oss->mmapped) { err = munmap (oss->pcm_buf, hw->samples << hw->info.shift); if (err) { oss_logerr (errno, "Failed to unmap buffer %p size %d\n", oss->pcm_buf, hw->samples << hw->info.shift); } } } } if (!oss->mmapped) { oss->pcm_buf = audio_calloc ( AUDIO_FUNC, hw->samples, 1 << hw->info.shift ); if (!oss->pcm_buf) { dolog ( "Could not allocate DAC buffer (%d samples, each %d bytes)\n", hw->samples, 1 << hw->info.shift ); oss_anal_close (&fd); return -1; } } oss->fd = fd; return 0;}static int oss_ctl_out (HWVoiceOut *hw, int cmd, ...){ int trig; OSSVoiceOut *oss = (OSSVoiceOut *) hw; if (!oss->mmapped) { return 0; } switch (cmd) { case VOICE_ENABLE: ldebug ("enabling voice\n"); audio_pcm_info_clear_buf (&hw->info, oss->pcm_buf, hw->samples); trig = PCM_ENABLE_OUTPUT; if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) { oss_logerr ( errno, "SNDCTL_DSP_SETTRIGGER PCM_ENABLE_OUTPUT failed\n" ); return -1; } break; case VOICE_DISABLE: ldebug ("disabling voice\n"); trig = 0; if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) { oss_logerr (errno, "SNDCTL_DSP_SETTRIGGER 0 failed\n"); return -1; } break; } return 0;}static int oss_init_in (HWVoiceIn *hw, audsettings_t *as){ OSSVoiceIn *oss = (OSSVoiceIn *) hw; struct oss_params req, obt; int endianness; int err; int fd; audfmt_e effective_fmt; audsettings_t obt_as; oss->fd = -1; req.fmt = aud_to_ossfmt (as->fmt); req.freq = as->freq; req.nchannels = as->nchannels; req.fragsize = conf.fragsize; req.nfrags = conf.nfrags; if (oss_open (1, &req, &obt, &fd)) { return -1; } err = oss_to_audfmt (obt.fmt, &effective_fmt, &endianness); if (err) { oss_anal_close (&fd); return -1; } obt_as.freq = obt.freq; obt_as.nchannels = obt.nchannels; obt_as.fmt = effective_fmt; audio_pcm_init_info ( &hw->info, &obt_as, audio_need_to_swap_endian (endianness) ); oss->nfrags = obt.nfrags; oss->fragsize = obt.fragsize; if (obt.nfrags * obt.fragsize & hw->info.align) { dolog ("warning: Misaligned ADC buffer, size %d, alignment %d\n", obt.nfrags * obt.fragsize, hw->info.align + 1); } hw->samples = (obt.nfrags * obt.fragsize) >> hw->info.shift; oss->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift); if (!oss->pcm_buf) { dolog ("Could not allocate ADC buffer (%d samples, each %d bytes)\n", hw->samples, 1 << hw->info.shift); oss_anal_close (&fd); return -1; } oss->fd = fd; return 0;}static void oss_fini_in (HWVoiceIn *hw){ OSSVoiceIn *oss = (OSSVoiceIn *) hw; oss_anal_close (&oss->fd); if (oss->pcm_buf) { qemu_free (oss->pcm_buf); oss->pcm_buf = NULL; }}static int oss_run_in (HWVoiceIn *hw){ OSSVoiceIn *oss = (OSSVoiceIn *) hw; int hwshift = hw->info.shift; int i; int live = audio_pcm_hw_get_live_in (hw); int dead = hw->samples - live; size_t read_samples = 0; struct { int add; int len; } bufs[2] = { { hw->wpos, 0 }, { 0, 0 } }; if (!dead) { return 0; } if (hw->wpos + dead > hw->samples) { bufs[0].len = (hw->samples - hw->wpos) << hwshift; bufs[1].len = (dead - (hw->samples - hw->wpos)) << hwshift; } else { bufs[0].len = dead << hwshift; } for (i = 0; i < 2; ++i) { ssize_t nread; if (bufs[i].len) { void *p = advance (oss->pcm_buf, bufs[i].add << hwshift); nread = read (oss->fd, p, bufs[i].len); if (nread > 0) { if (nread & hw->info.align) { dolog ("warning: Misaligned read %zd (requested %d), " "alignment %d\n", nread, bufs[i].add << hwshift, hw->info.align + 1); } read_samples += nread >> hwshift; hw->conv (hw->conv_buf + bufs[i].add, p, nread >> hwshift, &nominal_volume); } if (bufs[i].len - nread) { if (nread == -1) { switch (errno) { case EINTR: case EAGAIN: break; default: oss_logerr ( errno, "Failed to read %d bytes of audio (to %p)\n", bufs[i].len, p ); break; } } break; } } } hw->wpos = (hw->wpos + read_samples) % hw->samples; return read_samples;}static int oss_read (SWVoiceIn *sw, void *buf, int size){ return audio_pcm_sw_read (sw, buf, size);}static int oss_ctl_in (HWVoiceIn *hw, int cmd, ...){ (void) hw; (void) cmd; return 0;}static void *oss_audio_init (void){ return &conf;}static void oss_audio_fini (void *opaque){ (void) opaque;}static struct audio_option oss_options[] = { {"FRAGSIZE", AUD_OPT_INT, &conf.fragsize, "Fragment size in bytes", NULL, 0}, {"NFRAGS", AUD_OPT_INT, &conf.nfrags, "Number of fragments", NULL, 0}, {"MMAP", AUD_OPT_BOOL, &conf.try_mmap, "Try using memory mapped access", NULL, 0}, {"DAC_DEV", AUD_OPT_STR, &conf.devpath_out, "Path to DAC device", NULL, 0}, {"ADC_DEV", AUD_OPT_STR, &conf.devpath_in, "Path to ADC device", NULL, 0}, {NULL, 0, NULL, NULL, NULL, 0}};static struct audio_pcm_ops oss_pcm_ops = { oss_init_out, oss_fini_out, oss_run_out, oss_write, oss_ctl_out, oss_init_in, oss_fini_in, oss_run_in, oss_read, oss_ctl_in};struct audio_driver oss_audio_driver = { INIT_FIELD (name = ) "oss", INIT_FIELD (descr = ) "OSS http://www.opensound.com", INIT_FIELD (options = ) oss_options, INIT_FIELD (init = ) oss_audio_init, INIT_FIELD (fini = ) oss_audio_fini, INIT_FIELD (pcm_ops = ) &oss_pcm_ops, INIT_FIELD (can_be_default = ) 1, INIT_FIELD (max_voices_out = ) INT_MAX, INIT_FIELD (max_voices_in = ) INT_MAX, INIT_FIELD (voice_size_out = ) sizeof (OSSVoiceOut), INIT_FIELD (voice_size_in = ) sizeof (OSSVoiceIn)};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -