Beispiel #1
0
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;
}
Beispiel #2
0
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;
}
Beispiel #3
0
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;
}
Beispiel #4
0
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;
}