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 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, 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 dsound_run_out (HWVoiceOut *hw) { int err; HRESULT hr; DSoundVoiceOut *ds = (DSoundVoiceOut *) hw; LPDIRECTSOUNDBUFFER dsb = ds->dsound_buffer; int live, len, hwshift; DWORD blen1, blen2; DWORD len1, len2; DWORD decr; DWORD wpos, ppos, old_pos; LPVOID p1, p2; int bufsize; if (!dsb) { dolog ("Attempt to run empty with playback buffer\n"); return 0; } hwshift = hw->info.shift; bufsize = hw->samples << hwshift; live = audio_pcm_hw_get_live_out (hw); hr = IDirectSoundBuffer_GetCurrentPosition ( dsb, &ppos, ds->first_time ? &wpos : NULL ); if (FAILED (hr)) { dsound_logerr (hr, "Could not get playback buffer position\n"); return 0; } len = live << hwshift; if (ds->first_time) { if (conf.latency_millis) { DWORD cur_blat; cur_blat = audio_ring_dist (wpos, ppos, bufsize); ds->first_time = 0; old_pos = wpos; old_pos += millis_to_bytes (&hw->info, conf.latency_millis) - cur_blat; old_pos %= bufsize; old_pos &= ~hw->info.align; } else { old_pos = wpos; } #ifdef DEBUG_DSOUND ds->played = 0; ds->mixed = 0; #endif } else { if (ds->old_pos == ppos) { #ifdef DEBUG_DSOUND dolog ("old_pos == ppos\n"); #endif return 0; } #ifdef DEBUG_DSOUND ds->played += audio_ring_dist (ds->old_pos, ppos, hw->bufsize); #endif old_pos = ds->old_pos; } if ((old_pos < ppos) && ((old_pos + len) > ppos)) { len = ppos - old_pos; } else { if ((old_pos > ppos) && ((old_pos + len) > (ppos + bufsize))) { len = bufsize - old_pos + ppos; } } if (audio_bug (AUDIO_FUNC, len < 0 || len > bufsize)) { dolog ("len=%d bufsize=%d old_pos=%ld ppos=%ld\n", len, bufsize, old_pos, ppos); return 0; } len &= ~hw->info.align; if (!len) { return 0; } #ifdef DEBUG_DSOUND ds->old_ppos = ppos; #endif err = dsound_lock_out ( dsb, &hw->info, old_pos, len, &p1, &p2, &blen1, &blen2, 0 ); if (err) { return 0; } len1 = blen1 >> hwshift; len2 = blen2 >> hwshift; decr = len1 + len2; if (p1 && len1) { dsound_write_sample (hw, p1, len1); } if (p2 && len2) { dsound_write_sample (hw, p2, len2); } dsound_unlock_out (dsb, p1, p2, blen1, blen2); ds->old_pos = (old_pos + (decr << hwshift)) % bufsize; #ifdef DEBUG_DSOUND ds->mixed += decr << hwshift; dolog ("played %lu mixed %lu diff %ld sec %f\n", ds->played, ds->mixed, ds->mixed - ds->played, abs (ds->mixed - ds->played) / (double) hw->info.bytes_per_second); #endif return decr; }
static int winaudio_out_run (HWVoiceOut *hw) { WinAudioOut* s = (WinAudioOut*) hw; int played = 0; int has_buffer; int live = audio_pcm_hw_get_live_out (hw); 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); st_sample_t* 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; }