⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dsoundaudio.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * QEMU DirectSound audio driver * * Copyright (c) 2005 Vassili Karpov (malc) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. *//* * SEAL 1.07 by Carlos 'pel' Hasan was used as documentation */#include "vl.h"#define AUDIO_CAP "dsound"#include "audio_int.h"#include <windows.h>#include <objbase.h>#include <dsound.h>/* #define DEBUG_DSOUND */static struct {    int lock_retries;    int restore_retries;    int getstatus_retries;    int set_primary;    int bufsize_in;    int bufsize_out;    audsettings_t settings;    int latency_millis;} conf = {    1,    1,    1,    0,    16384,    16384,    {        44100,        2,        AUD_FMT_S16    },    10};typedef struct {    LPDIRECTSOUND dsound;    LPDIRECTSOUNDCAPTURE dsound_capture;    LPDIRECTSOUNDBUFFER dsound_primary_buffer;    audsettings_t settings;} dsound;static dsound glob_dsound;typedef struct {    HWVoiceOut hw;    LPDIRECTSOUNDBUFFER dsound_buffer;    DWORD old_pos;    int first_time;#ifdef DEBUG_DSOUND    DWORD old_ppos;    DWORD played;    DWORD mixed;#endif} DSoundVoiceOut;typedef struct {    HWVoiceIn hw;    int first_time;    LPDIRECTSOUNDCAPTUREBUFFER dsound_capture_buffer;} DSoundVoiceIn;static void dsound_log_hresult (HRESULT hr){    const char *str = "BUG";    switch (hr) {    case DS_OK:        str = "The method succeeded";        break;#ifdef DS_NO_VIRTUALIZATION    case DS_NO_VIRTUALIZATION:        str = "The buffer was created, but another 3D algorithm was substituted";        break;#endif#ifdef DS_INCOMPLETE    case DS_INCOMPLETE:        str = "The method succeeded, but not all the optional effects were obtained";        break;#endif#ifdef DSERR_ACCESSDENIED    case DSERR_ACCESSDENIED:        str = "The request failed because access was denied";        break;#endif#ifdef DSERR_ALLOCATED    case DSERR_ALLOCATED:        str = "The request failed because resources, such as a priority level, were already in use by another caller";        break;#endif#ifdef DSERR_ALREADYINITIALIZED    case DSERR_ALREADYINITIALIZED:        str = "The object is already initialized";        break;#endif#ifdef DSERR_BADFORMAT    case DSERR_BADFORMAT:        str = "The specified wave format is not supported";        break;#endif#ifdef DSERR_BADSENDBUFFERGUID    case DSERR_BADSENDBUFFERGUID:        str = "The GUID specified in an audiopath file does not match a valid mix-in buffer";        break;#endif#ifdef DSERR_BUFFERLOST    case DSERR_BUFFERLOST:        str = "The buffer memory has been lost and must be restored";        break;#endif#ifdef DSERR_BUFFERTOOSMALL    case DSERR_BUFFERTOOSMALL:        str = "The buffer size is not great enough to enable effects processing";        break;#endif#ifdef DSERR_CONTROLUNAVAIL    case DSERR_CONTROLUNAVAIL:        str = "The buffer control (volume, pan, and so on) requested by the caller is not available. Controls must be specified when the buffer is created, using the dwFlags member of DSBUFFERDESC";        break;#endif#ifdef DSERR_DS8_REQUIRED    case DSERR_DS8_REQUIRED:        str = "A DirectSound object of class CLSID_DirectSound8 or later is required for the requested functionality. For more information, see IDirectSound8 Interface";        break;#endif#ifdef DSERR_FXUNAVAILABLE    case DSERR_FXUNAVAILABLE:        str = "The effects requested could not be found on the system, or they are in the wrong order or in the wrong location; for example, an effect expected in hardware was found in software";        break;#endif#ifdef DSERR_GENERIC    case DSERR_GENERIC :        str = "An undetermined error occurred inside the DirectSound subsystem";        break;#endif#ifdef DSERR_INVALIDCALL    case DSERR_INVALIDCALL:        str = "This function is not valid for the current state of this object";        break;#endif#ifdef DSERR_INVALIDPARAM    case DSERR_INVALIDPARAM:        str = "An invalid parameter was passed to the returning function";        break;#endif#ifdef DSERR_NOAGGREGATION    case DSERR_NOAGGREGATION:        str = "The object does not support aggregation";        break;#endif#ifdef DSERR_NODRIVER    case DSERR_NODRIVER:        str = "No sound driver is available for use, or the given GUID is not a valid DirectSound device ID";        break;#endif#ifdef DSERR_NOINTERFACE    case DSERR_NOINTERFACE:        str = "The requested COM interface is not available";        break;#endif#ifdef DSERR_OBJECTNOTFOUND    case DSERR_OBJECTNOTFOUND:        str = "The requested object was not found";        break;#endif#ifdef DSERR_OTHERAPPHASPRIO    case DSERR_OTHERAPPHASPRIO:        str = "Another application has a higher priority level, preventing this call from succeeding";        break;#endif#ifdef DSERR_OUTOFMEMORY    case DSERR_OUTOFMEMORY:        str = "The DirectSound subsystem could not allocate sufficient memory to complete the caller's request";        break;#endif#ifdef DSERR_PRIOLEVELNEEDED    case DSERR_PRIOLEVELNEEDED:        str = "A cooperative level of DSSCL_PRIORITY or higher is required";        break;#endif#ifdef DSERR_SENDLOOP    case DSERR_SENDLOOP:        str = "A circular loop of send effects was detected";        break;#endif#ifdef DSERR_UNINITIALIZED    case DSERR_UNINITIALIZED:        str = "The Initialize method has not been called or has not been called successfully before other methods were called";        break;#endif#ifdef DSERR_UNSUPPORTED    case DSERR_UNSUPPORTED:        str = "The function called is not supported at this time";        break;#endif    default:        AUD_log (AUDIO_CAP, "Reason: Unknown (HRESULT %#lx)\n", hr);        return;    }    AUD_log (AUDIO_CAP, "Reason: %s\n", str);}static void GCC_FMT_ATTR (2, 3) dsound_logerr (    HRESULT hr,    const char *fmt,    ...    ){    va_list ap;    va_start (ap, fmt);    AUD_vlog (AUDIO_CAP, fmt, ap);    va_end (ap);    dsound_log_hresult (hr);}static void GCC_FMT_ATTR (3, 4) dsound_logerr2 (    HRESULT hr,    const char *typ,    const char *fmt,    ...    ){    va_list ap;    AUD_log (AUDIO_CAP, "Could not initialize %s\n", typ);    va_start (ap, fmt);    AUD_vlog (AUDIO_CAP, fmt, ap);    va_end (ap);    dsound_log_hresult (hr);}static DWORD millis_to_bytes (struct audio_pcm_info *info, DWORD millis){    return (millis * info->bytes_per_second) / 1000;}#ifdef DEBUG_DSOUNDstatic void print_wave_format (WAVEFORMATEX *wfx){    dolog ("tag             = %d\n", wfx->wFormatTag);    dolog ("nChannels       = %d\n", wfx->nChannels);    dolog ("nSamplesPerSec  = %ld\n", wfx->nSamplesPerSec);    dolog ("nAvgBytesPerSec = %ld\n", wfx->nAvgBytesPerSec);    dolog ("nBlockAlign     = %d\n", wfx->nBlockAlign);    dolog ("wBitsPerSample  = %d\n", wfx->wBitsPerSample);    dolog ("cbSize          = %d\n", wfx->cbSize);}#endifstatic int dsound_restore_out (LPDIRECTSOUNDBUFFER dsb){    HRESULT hr;    int i;    for (i = 0; i < conf.restore_retries; ++i) {        hr = IDirectSoundBuffer_Restore (dsb);        switch (hr) {        case DS_OK:            return 0;        case DSERR_BUFFERLOST:            continue;        default:            dsound_logerr (hr, "Could not restore playback buffer\n");            return -1;        }    }    dolog ("%d attempts to restore playback buffer failed\n", i);    return -1;}static int waveformat_from_audio_settings (WAVEFORMATEX *wfx, audsettings_t *as){    memset (wfx, 0, sizeof (*wfx));    wfx->wFormatTag = WAVE_FORMAT_PCM;    wfx->nChannels = as->nchannels;    wfx->nSamplesPerSec = as->freq;    wfx->nAvgBytesPerSec = as->freq << (as->nchannels == 2);    wfx->nBlockAlign = 1 << (as->nchannels == 2);    wfx->cbSize = 0;    switch (as->fmt) {    case AUD_FMT_S8:        wfx->wBitsPerSample = 8;        break;    case AUD_FMT_U8:        wfx->wBitsPerSample = 8;        break;    case AUD_FMT_S16:        wfx->wBitsPerSample = 16;        wfx->nAvgBytesPerSec <<= 1;        wfx->nBlockAlign <<= 1;        break;    case AUD_FMT_U16:        wfx->wBitsPerSample = 16;        wfx->nAvgBytesPerSec <<= 1;        wfx->nBlockAlign <<= 1;        break;    default:        dolog ("Internal logic error: Bad audio format %d\n", as->freq);        return -1;    }    return 0;}static int waveformat_to_audio_settings (WAVEFORMATEX *wfx, audsettings_t *as){    if (wfx->wFormatTag != WAVE_FORMAT_PCM) {        dolog ("Invalid wave format, tag is not PCM, but %d\n",               wfx->wFormatTag);        return -1;    }    if (!wfx->nSamplesPerSec) {        dolog ("Invalid wave format, frequency is zero\n");        return -1;    }    as->freq = wfx->nSamplesPerSec;    switch (wfx->nChannels) {    case 1:        as->nchannels = 1;        break;    case 2:        as->nchannels = 2;        break;    default:        dolog (            "Invalid wave format, number of channels is not 1 or 2, but %d\n",            wfx->nChannels            );        return -1;    }    switch (wfx->wBitsPerSample) {    case 8:        as->fmt = AUD_FMT_U8;        break;    case 16:        as->fmt = AUD_FMT_S16;        break;    default:        dolog ("Invalid wave format, bits per sample is not 8 or 16, but %d\n",               wfx->wBitsPerSample);        return -1;    }    return 0;}#include "dsound_template.h"#define DSBTYPE_IN#include "dsound_template.h"#undef DSBTYPE_INstatic int dsound_get_status_out (LPDIRECTSOUNDBUFFER dsb, DWORD *statusp){    HRESULT hr;    int i;    for (i = 0; i < conf.getstatus_retries; ++i) {        hr = IDirectSoundBuffer_GetStatus (dsb, statusp);        if (FAILED (hr)) {            dsound_logerr (hr, "Could not get playback buffer status\n");            return -1;        }        if (*statusp & DSERR_BUFFERLOST) {            if (dsound_restore_out (dsb)) {                return -1;            }            continue;        }        break;    }    return 0;}static int dsound_get_status_in (LPDIRECTSOUNDCAPTUREBUFFER dscb,                                 DWORD *statusp){    HRESULT hr;    hr = IDirectSoundCaptureBuffer_GetStatus (dscb, statusp);    if (FAILED (hr)) {        dsound_logerr (hr, "Could not get capture buffer status\n");        return -1;    }    return 0;}static void dsound_write_sample (HWVoiceOut *hw, uint8_t *dst, int dst_len){    int src_len1 = dst_len;    int src_len2 = 0;    int pos = hw->rpos + dst_len;    st_sample_t *src1 = hw->mix_buf + hw->rpos;    st_sample_t *src2 = NULL;    if (pos > hw->samples) {        src_len1 = hw->samples - hw->rpos;        src2 = hw->mix_buf;        src_len2 = dst_len - src_len1;        pos = src_len2;    }    if (src_len1) {        hw->clip (dst, src1, src_len1);    }    if (src_len2) {        dst = advance (dst, src_len1 << hw->info.shift);        hw->clip (dst, src2, src_len2);    }    hw->rpos = pos % hw->samples;}static void dsound_clear_sample (HWVoiceOut *hw, LPDIRECTSOUNDBUFFER dsb){    int err;    LPVOID p1, p2;    DWORD blen1, blen2, len1, len2;    err = dsound_lock_out (        dsb,        &hw->info,        0,        hw->samples << hw->info.shift,        &p1, &p2,        &blen1, &blen2,        1        );    if (err) {        return;    }    len1 = blen1 >> hw->info.shift;    len2 = blen2 >> hw->info.shift;#ifdef DEBUG_DSOUND    dolog ("clear %p,%ld,%ld %p,%ld,%ld\n",           p1, blen1, len1,           p2, blen2, len2);#endif    if (p1 && len1) {        audio_pcm_info_clear_buf (&hw->info, p1, len1);    }    if (p2 && len2) {        audio_pcm_info_clear_buf (&hw->info, p2, len2);    }    dsound_unlock_out (dsb, p1, p2, blen1, blen2);}static void dsound_close (dsound *s){    HRESULT hr;    if (s->dsound_primary_buffer) {        hr = IDirectSoundBuffer_Release (s->dsound_primary_buffer);        if (FAILED (hr)) {            dsound_logerr (hr, "Could not release primary buffer\n");        }        s->dsound_primary_buffer = NULL;    }}static int dsound_open (dsound *s){    int err;    HRESULT hr;    WAVEFORMATEX wfx;    DSBUFFERDESC dsbd;    HWND hwnd;    hwnd = GetForegroundWindow ();    hr = IDirectSound_SetCooperativeLevel (        s->dsound,        hwnd,        DSSCL_PRIORITY        );    if (FAILED (hr)) {        dsound_logerr (hr, "Could not set cooperative level for window %p\n",                       hwnd);        return -1;    }    if (!conf.set_primary) {        return 0;    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -