static int winwave_run_in (HWVoiceIn *hw) { WaveVoiceIn *wave = (WaveVoiceIn *) hw; int live = audio_pcm_hw_get_live_in (hw); int dead = hw->samples - live; int decr, ret; if (!dead) { return 0; } EnterCriticalSection (&wave->crit_sect); { decr = audio_MIN (dead, wave->avail); wave->avail -= decr; } LeaveCriticalSection (&wave->crit_sect); ret = decr; while (decr) { int left = hw->samples - hw->wpos; int conv = audio_MIN (left, decr); hw->conv (hw->conv_buf + hw->wpos, advance (wave->pcm_buf, wave->rpos << hw->info.shift), conv); wave->rpos = (wave->rpos + conv) % hw->samples; hw->wpos = (hw->wpos + conv) % hw->samples; decr -= conv; } winwave_add_buffers (wave, ret); return ret; }
static int coreaudio_run_out (HWVoiceOut *hw, int live) { int decr; coreaudioVoice *core = CORE_OUT(hw); if (coreaudio_voice_lock (core, "coreaudio_run_out")) { return 0; } if (core->decr > live) { ldebug ("core->decr %d live %d core->live %d\n", core->decr, live, core->live); } decr = audio_MIN (core->decr, live); core->decr -= decr; core->live = live - decr; hw->rpos = core->pos; coreaudio_voice_unlock (core, "coreaudio_run_out"); return decr; }
static int cs_write_audio (CSState *s, int nchan, int dma_pos, int dma_len, int len) { int temp, net; uint8_t tmpbuf[4096]; temp = len; net = 0; while (temp) { int left = dma_len - dma_pos; int copied; size_t to_copy; to_copy = audio_MIN (temp, left); if (to_copy > sizeof (tmpbuf)) { to_copy = sizeof (tmpbuf); } copied = DMA_read_memory (nchan, tmpbuf, dma_pos, to_copy); if (s->tab) { int i; int16_t linbuf[4096]; for (i = 0; i < copied; ++i) linbuf[i] = s->tab[tmpbuf[i]]; copied = AUD_write (s->voice, linbuf, copied << 1); copied >>= 1; } else {
static int genode_run_out(HWVoiceOut *hw) { GenodeVoiceOut * const out = (GenodeVoiceOut *)hw; Pcm_out_buffer & pcm_buf = out->pcm_buf; int const live = audio_pcm_hw_get_live_out(&out->hw); if (!live) return 0; int const decr = audio_MIN(live, out->hw.samples); size_t const avail = pcm_buf.read_avail(); if ((avail / (VBOX_SAMPLE_SIZE*VBOX_CHANNELS)) < decr) Genode::error(__func__, ": avail: ", avail, " < decr ", decr); char buf[decr*VBOX_SAMPLE_SIZE*VBOX_CHANNELS]; pcm_buf.read(buf, sizeof(buf), true); int const samples = write_samples(out, (int16_t*)buf, decr); if (samples == 0) return 0; pcm_buf.read_advance(samples * (VBOX_SAMPLE_SIZE*VBOX_CHANNELS)); out->hw.rpos = (out->hw.rpos + samples) % out->hw.samples; return samples; }
static void ac97_in_cb(void *opaque, int avail_b) { MilkymistAC97State *s = opaque; uint8_t buf[4096]; uint32_t remaining = s->regs[R_U_REMAINING]; int temp = audio_MIN(remaining, avail_b); uint32_t addr = s->regs[R_U_ADDR]; int transferred = 0; trace_milkymist_ac97_in_cb(avail_b, remaining); /* prevent from raising an IRQ */ if (temp == 0) { return; } while (temp) { int acquired, to_copy; to_copy = audio_MIN(temp, sizeof(buf)); acquired = AUD_read(s->voice_in, buf, to_copy); if (!acquired) { break; } cpu_physical_memory_write(addr, buf, acquired); temp -= acquired; addr += acquired; transferred += acquired; } trace_milkymist_ac97_in_cb_transferred(transferred); s->regs[R_U_ADDR] = addr; s->regs[R_U_REMAINING] -= transferred; if ((s->regs[R_U_CTRL] & CTRL_EN) && (s->regs[R_U_REMAINING] == 0)) { trace_milkymist_ac97_pulse_irq_dmaw(); qemu_irq_pulse(s->dmaw_irq); } }
/* capture */ static int qesd_run_in (HWVoiceIn *hw) { int wpos, liveSamples, totalSamples; int grabSamples; ESDVoiceIn *esd = (ESDVoiceIn *) hw; wpos = hw->wpos; liveSamples = audio_pcm_hw_get_live_in (hw); grabSamples = hw->samples - liveSamples; totalSamples = 0; while (grabSamples > 0) { ssize_t nread; int chunkSamples = audio_MIN (grabSamples, hw->samples - wpos); int chunkBytes = chunkSamples << hw->info.shift; int readSamples, readBytes; void* buf = advance (esd->pcm_buf, wpos); AGAIN: nread = read (esd->fd, buf, chunkBytes); if (nread == -1) { if (errno == EINTR) goto AGAIN; if (errno == EAGAIN || errno == EWOULDBLOCK) break; qesd_logerr (errno, "read failed: %s\n", strerror(errno)); break; } if (nread == 0) break; readSamples = nread >> hw->info.shift; readBytes = readSamples << hw->info.shift; if (readBytes != nread) { dolog ("warning: Misaligned read %d (requested %d), " "alignment %d\n", nread, readBytes, hw->info.align + 1); } hw->conv (hw->conv_buf + wpos, buf, readSamples, &nominal_volume); wpos = (wpos + readSamples) % hw->samples; grabSamples -= readSamples; totalSamples += readSamples; } hw->wpos = wpos; return totalSamples; }
static int qesd_run_out (HWVoiceOut *hw) { ESDVoiceOut *esd = (ESDVoiceOut *) hw; int liveSamples, totalSamples; int rpos, nwrite, writeSamples, writeBytes; liveSamples = audio_pcm_hw_get_live_out (hw); rpos = hw->rpos; totalSamples = 0; while (liveSamples > 0) { int chunkSamples = audio_MIN (liveSamples, hw->samples - rpos); int chunkBytes = chunkSamples << hw->info.shift; struct st_sample *src = hw->mix_buf + rpos; hw->clip (esd->pcm_buf, src, chunkSamples); AGAIN: nwrite = write (esd->fd, esd->pcm_buf, chunkBytes); if (nwrite == -1) { if (errno == EINTR) goto AGAIN; if (errno == EAGAIN || errno == EWOULDBLOCK) break; qesd_logerr (errno, "write failed: %s\n", strerror(errno)); O("EsounD output thread write error: %s", strerror(errno)); break; } if (nwrite == 0) break; writeSamples = nwrite >> hw->info.shift; writeBytes = writeSamples << hw->info.shift; if (writeBytes != nwrite) { dolog ("warning: Misaligned write %d (requested %d), " "alignment %d\n", nwrite, writeBytes, hw->info.align + 1); } rpos = (rpos + writeSamples) % hw->samples; totalSamples += writeSamples; liveSamples -= writeSamples; } hw->rpos = rpos; return totalSamples; }
static int qpa_run_out (HWVoiceOut *hw, int live) { int decr; PAVoiceOut *pa = (PAVoiceOut *) hw; if (audio_pt_lock(&pa->pt, __func__)) { return 0; } decr = audio_MIN (live, pa->decr); pa->decr -= decr; pa->live = live - decr; hw->rpos = pa->rpos; if (pa->live > 0) { audio_pt_unlock_and_signal(&pa->pt, __func__); } else { audio_pt_unlock(&pa->pt, __func__); } return decr; }
static int qpa_run_out (HWVoiceOut *hw) { int live, decr; PAVoiceOut *pa = (PAVoiceOut *) hw; if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) { return 0; } live = audio_pcm_hw_get_live_out (hw); decr = audio_MIN (live, pa->decr); pa->decr -= decr; pa->live = live - decr; hw->rpos = pa->rpos; if (pa->live > 0) { audio_pt_unlock_and_signal (&pa->pt, AUDIO_FUNC); } else { audio_pt_unlock (&pa->pt, AUDIO_FUNC); } return decr; }
static int qpa_run_in (HWVoiceIn *hw) { int live, incr, dead; PAVoiceIn *pa = (PAVoiceIn *) hw; if (audio_pt_lock(&pa->pt, __func__)) { return 0; } live = audio_pcm_hw_get_live_in (hw); dead = hw->samples - live; incr = audio_MIN (dead, pa->incr); pa->incr -= incr; pa->dead = dead - incr; hw->wpos = pa->wpos; if (pa->dead > 0) { audio_pt_unlock_and_signal(&pa->pt, __func__); } else { audio_pt_unlock(&pa->pt, __func__); } return incr; }
static int winwave_run_out (HWVoiceOut *hw, int live) { WaveVoiceOut *wave = (WaveVoiceOut *) hw; int decr; int doreset; EnterCriticalSection (&wave->crit_sect); { decr = audio_MIN (live, wave->avail); decr = audio_pcm_hw_clip_out (hw, wave->pcm_buf, decr, wave->pending); wave->pending += decr; wave->avail -= decr; } LeaveCriticalSection (&wave->crit_sect); doreset = hw->poll_mode && (wave->pending >= conf.dac_samples); if (doreset && !ResetEvent (wave->event)) { dolog ("DAC ResetEvent failed %lx\n", GetLastError ()); } while (wave->pending >= conf.dac_samples) { MMRESULT mr; WAVEHDR *h = &wave->hdrs[wave->curhdr]; h->dwUser = 0; mr = waveOutWrite (wave->hwo, h, sizeof (*h)); if (mr != MMSYSERR_NOERROR) { winwave_logerr (mr, "waveOutWrite(%d)", wave->curhdr); break; } wave->pending -= conf.dac_samples; wave->curhdr = (wave->curhdr + 1) % conf.dac_headers; } return decr; }
/* capture */ static void *qpa_thread_in (void *arg) { PAVoiceIn *pa = arg; HWVoiceIn *hw = &pa->hw; if (audio_pt_lock(&pa->pt, __func__)) { return NULL; } for (;;) { int incr, to_grab, wpos; for (;;) { if (pa->done) { goto exit; } if (pa->dead > 0) { break; } if (audio_pt_wait(&pa->pt, __func__)) { goto exit; } } incr = to_grab = audio_MIN(pa->dead, pa->samples >> 5); wpos = pa->wpos; if (audio_pt_unlock(&pa->pt, __func__)) { return NULL; } while (to_grab) { int error; int chunk = audio_MIN (to_grab, hw->samples - wpos); void *buf = advance (pa->pcm_buf, wpos); if (qpa_simple_read (pa, buf, chunk << hw->info.shift, &error) < 0) { qpa_logerr (error, "pa_simple_read failed\n"); return NULL; } hw->conv (hw->conv_buf + wpos, buf, chunk); wpos = (wpos + chunk) % hw->samples; to_grab -= chunk; } if (audio_pt_lock(&pa->pt, __func__)) { return NULL; } pa->wpos = wpos; pa->dead -= incr; pa->incr += incr; } exit: audio_pt_unlock(&pa->pt, __func__); return NULL; }
static void *qpa_thread_out (void *arg) { PAVoiceOut *pa = arg; HWVoiceOut *hw = &pa->hw; if (audio_pt_lock(&pa->pt, __func__)) { return NULL; } for (;;) { int decr, to_mix, rpos; for (;;) { if (pa->done) { goto exit; } if (pa->live > 0) { break; } if (audio_pt_wait(&pa->pt, __func__)) { goto exit; } } decr = to_mix = audio_MIN(pa->live, pa->samples >> 5); rpos = pa->rpos; if (audio_pt_unlock(&pa->pt, __func__)) { return NULL; } while (to_mix) { int error; int chunk = audio_MIN (to_mix, hw->samples - rpos); struct st_sample *src = hw->mix_buf + rpos; hw->clip (pa->pcm_buf, src, chunk); if (qpa_simple_write (pa, pa->pcm_buf, chunk << hw->info.shift, &error) < 0) { qpa_logerr (error, "pa_simple_write failed\n"); return NULL; } rpos = (rpos + chunk) % hw->samples; to_mix -= chunk; } if (audio_pt_lock(&pa->pt, __func__)) { return NULL; } pa->rpos = rpos; pa->live -= decr; pa->decr += decr; } exit: audio_pt_unlock(&pa->pt, __func__); return NULL; }
/* capture */ static void *qpa_thread_in (void *arg) { PAVoiceIn *pa = arg; HWVoiceIn *hw = &pa->hw; int threshold; threshold = conf.divisor ? hw->samples / conf.divisor : 0; if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) { return NULL; } for (;;) { int incr, to_grab, wpos; for (;;) { if (pa->done) { goto exit; } if (pa->dead > threshold) { break; } if (audio_pt_wait (&pa->pt, AUDIO_FUNC)) { goto exit; } } incr = to_grab = pa->dead; wpos = hw->wpos; if (audio_pt_unlock (&pa->pt, AUDIO_FUNC)) { return NULL; } while (to_grab) { int error; int chunk = audio_MIN (to_grab, hw->samples - wpos); void *buf = advance (pa->pcm_buf, wpos); if (FF(pa_simple_read) (pa->s, buf, chunk << hw->info.shift, &error) < 0) { qpa_logerr (error, "pa_simple_read failed\n"); return NULL; } hw->conv (hw->conv_buf + wpos, buf, chunk, &nominal_volume); wpos = (wpos + chunk) % hw->samples; to_grab -= chunk; } if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) { return NULL; } pa->wpos = wpos; pa->dead -= incr; pa->incr += incr; } exit: audio_pt_unlock (&pa->pt, AUDIO_FUNC); return NULL; }
/* report the number of captured samples to the audio subsystem */ static int winaudio_in_run (HWVoiceIn *hw) { WinAudioIn* s = (WinAudioIn*) hw; int captured = 0; int has_buffer; int live = hw->samples - hw->total_samples_captured; if (!live) { #if 0 static int counter; if (++counter == 100) { D("0"); fflush(stdout); counter = 0; } #endif return 0; } EnterCriticalSection( &s->lock ); has_buffer = (s->read_count > 0); LeaveCriticalSection( &s->lock ); if (has_buffer > 0) { while (live > 0) { WAVEHDR* wav_buffer = s->buffers + s->read_index; int wav_bytes = (s->read_size - s->read_pos); int wav_samples = audio_MIN(wav_bytes >> hw->info.shift, live); int hw_samples = audio_MIN(hw->samples - hw->wpos, live); struct st_sample* dst = hw->conv_buf + hw->wpos; uint8_t* src = (uint8_t*)wav_buffer->lpData + s->read_pos; if (wav_samples > hw_samples) { wav_samples = hw_samples; } wav_bytes = wav_samples << hw->info.shift; D("%s: buffer:%d pos:%d size:%d wsamples:%d wbytes:%d live:%d wpos:%d hwsamples:%d\n", __FUNCTION__, s->read_index, s->read_pos, s->read_size, wav_samples, wav_bytes, live, hw->wpos, hw->samples); hw->conv(dst, src, wav_samples, &nominal_volume); hw->wpos += wav_samples; if (hw->wpos >= hw->samples) hw->wpos -= hw->samples; live -= wav_samples; captured += wav_samples; s->read_pos += wav_bytes; if (s->read_pos == s->read_size) { s->read_pos = 0; s->read_index += 1; if (s->read_index == NUM_IN_BUFFERS) s->read_index = 0; waveInAddBuffer( s->wavein, wav_buffer, sizeof(*wav_buffer) ); EnterCriticalSection( &s->lock ); if (--s->read_count == 0) { live = 0; } LeaveCriticalSection( &s->lock ); } } } return captured; }
static int winaudio_out_run (HWVoiceOut *hw, int live) { WinAudioOut* s = (WinAudioOut*) hw; int played = 0; int has_buffer; if (!live) { return 0; } EnterCriticalSection( &s->lock ); has_buffer = (s->write_count > 0); LeaveCriticalSection( &s->lock ); if (has_buffer) { while (live > 0) { WAVEHDR* wav_buffer = s->buffers + s->write_index; int wav_bytes = (s->write_size - s->write_pos); int wav_samples = audio_MIN(wav_bytes >> hw->info.shift, live); int hw_samples = audio_MIN(hw->samples - hw->rpos, live); struct st_sample* src = hw->mix_buf + hw->rpos; uint8_t* dst = (uint8_t*)wav_buffer->lpData + s->write_pos; if (wav_samples > hw_samples) { wav_samples = hw_samples; } wav_bytes = wav_samples << hw->info.shift; //D("run_out: buffer:%d pos:%d size:%d wsamples:%d wbytes:%d live:%d rpos:%d hwsamples:%d\n", s->write_index, // s->write_pos, s->write_size, wav_samples, wav_bytes, live, hw->rpos, hw->samples); hw->clip (dst, src, wav_samples); hw->rpos += wav_samples; if (hw->rpos >= hw->samples) hw->rpos -= hw->samples; live -= wav_samples; played += wav_samples; s->write_pos += wav_bytes; if (s->write_pos == s->write_size) { #if xxDEBUG int64_t now = qemu_get_clock(vm_clock) - start_time; int64_t diff = now - last_time; D("run_out: (%7.3f:%7d):waveOutWrite buffer:%d\n", now/1e9, (now-last_time)/1e9, s->write_index); last_time = now; #endif waveOutWrite( s->waveout, wav_buffer, sizeof(*wav_buffer) ); s->write_pos = 0; s->write_index += 1; if (s->write_index == NUM_OUT_BUFFERS) s->write_index = 0; EnterCriticalSection( &s->lock ); if (--s->write_count == 0) { live = 0; } LeaveCriticalSection( &s->lock ); } } } return played; }