📄 dsoundaudio.c
字号:
err = waveformat_from_audio_settings (&wfx, &conf.settings); if (err) { return -1; } memset (&dsbd, 0, sizeof (dsbd)); dsbd.dwSize = sizeof (dsbd); dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER; dsbd.dwBufferBytes = 0; dsbd.lpwfxFormat = NULL; hr = IDirectSound_CreateSoundBuffer ( s->dsound, &dsbd, &s->dsound_primary_buffer, NULL ); if (FAILED (hr)) { dsound_logerr (hr, "Could not create primary playback buffer\n"); return -1; } hr = IDirectSoundBuffer_SetFormat (s->dsound_primary_buffer, &wfx); if (FAILED (hr)) { dsound_logerr (hr, "Could not set primary playback buffer format\n"); } hr = IDirectSoundBuffer_GetFormat ( s->dsound_primary_buffer, &wfx, sizeof (wfx), NULL ); if (FAILED (hr)) { dsound_logerr (hr, "Could not get primary playback buffer format\n"); goto fail0; }#ifdef DEBUG_DSOUND dolog ("Primary\n"); print_wave_format (&wfx);#endif err = waveformat_to_audio_settings (&wfx, &s->settings); if (err) { goto fail0; } return 0; fail0: dsound_close (s); return -1;}static int dsound_ctl_out (HWVoiceOut *hw, int cmd, ...){ HRESULT hr; DWORD status; DSoundVoiceOut *ds = (DSoundVoiceOut *) hw; LPDIRECTSOUNDBUFFER dsb = ds->dsound_buffer; if (!dsb) { dolog ("Attempt to control voice without a buffer\n"); return 0; } switch (cmd) { case VOICE_ENABLE: if (dsound_get_status_out (dsb, &status)) { return -1; } if (status & DSBSTATUS_PLAYING) { dolog ("warning: Voice is already playing\n"); return 0; } dsound_clear_sample (hw, dsb); hr = IDirectSoundBuffer_Play (dsb, 0, 0, DSBPLAY_LOOPING); if (FAILED (hr)) { dsound_logerr (hr, "Could not start playing buffer\n"); return -1; } break; case VOICE_DISABLE: if (dsound_get_status_out (dsb, &status)) { return -1; } if (status & DSBSTATUS_PLAYING) { hr = IDirectSoundBuffer_Stop (dsb); if (FAILED (hr)) { dsound_logerr (hr, "Could not stop playing buffer\n"); return -1; } } else { dolog ("warning: Voice is not playing\n"); } break; } return 0;}static int dsound_write (SWVoiceOut *sw, void *buf, int len){ return audio_pcm_sw_write (sw, buf, len);}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 dsound_ctl_in (HWVoiceIn *hw, int cmd, ...){ HRESULT hr; DWORD status; DSoundVoiceIn *ds = (DSoundVoiceIn *) hw; LPDIRECTSOUNDCAPTUREBUFFER dscb = ds->dsound_capture_buffer; if (!dscb) { dolog ("Attempt to control capture voice without a buffer\n"); return -1; } switch (cmd) { case VOICE_ENABLE: if (dsound_get_status_in (dscb, &status)) { return -1; } if (status & DSCBSTATUS_CAPTURING) { dolog ("warning: Voice is already capturing\n"); return 0; } /* clear ?? */ hr = IDirectSoundCaptureBuffer_Start (dscb, DSCBSTART_LOOPING); if (FAILED (hr)) { dsound_logerr (hr, "Could not start capturing\n"); return -1; } break; case VOICE_DISABLE: if (dsound_get_status_in (dscb, &status)) { return -1; } if (status & DSCBSTATUS_CAPTURING) { hr = IDirectSoundCaptureBuffer_Stop (dscb); if (FAILED (hr)) { dsound_logerr (hr, "Could not stop capturing\n"); return -1; } } else { dolog ("warning: Voice is not capturing\n"); } break; } return 0;}static int dsound_read (SWVoiceIn *sw, void *buf, int len){ return audio_pcm_sw_read (sw, buf, len);}static int dsound_run_in (HWVoiceIn *hw){ int err; HRESULT hr; DSoundVoiceIn *ds = (DSoundVoiceIn *) hw; LPDIRECTSOUNDCAPTUREBUFFER dscb = ds->dsound_capture_buffer; int live, len, dead; DWORD blen1, blen2; DWORD len1, len2; DWORD decr; DWORD cpos, rpos; LPVOID p1, p2; int hwshift; if (!dscb) { dolog ("Attempt to run without capture buffer\n"); return 0; } hwshift = hw->info.shift; live = audio_pcm_hw_get_live_in (hw); dead = hw->samples - live; if (!dead) { return 0; } hr = IDirectSoundCaptureBuffer_GetCurrentPosition ( dscb, &cpos, ds->first_time ? &rpos : NULL ); if (FAILED (hr)) { dsound_logerr (hr, "Could not get capture buffer position\n"); return 0; } if (ds->first_time) { ds->first_time = 0; if (rpos & hw->info.align) { ldebug ("warning: Misaligned capture read position %ld(%d)\n", rpos, hw->info.align); } hw->wpos = rpos >> hwshift; } if (cpos & hw->info.align) { ldebug ("warning: Misaligned capture position %ld(%d)\n", cpos, hw->info.align); } cpos >>= hwshift; len = audio_ring_dist (cpos, hw->wpos, hw->samples); if (!len) { return 0; } len = audio_MIN (len, dead); err = dsound_lock_in ( dscb, &hw->info, hw->wpos << hwshift, len << hwshift, &p1, &p2, &blen1, &blen2, 0 ); if (err) { return 0; } len1 = blen1 >> hwshift; len2 = blen2 >> hwshift; decr = len1 + len2; if (p1 && len1) { hw->conv (hw->conv_buf + hw->wpos, p1, len1, &nominal_volume); } if (p2 && len2) { hw->conv (hw->conv_buf, p2, len2, &nominal_volume); } dsound_unlock_in (dscb, p1, p2, blen1, blen2); hw->wpos = (hw->wpos + decr) % hw->samples; return decr;}static void dsound_audio_fini (void *opaque){ HRESULT hr; dsound *s = opaque; if (!s->dsound) { return; } hr = IDirectSound_Release (s->dsound); if (FAILED (hr)) { dsound_logerr (hr, "Could not release DirectSound\n"); } s->dsound = NULL; if (!s->dsound_capture) { return; } hr = IDirectSoundCapture_Release (s->dsound_capture); if (FAILED (hr)) { dsound_logerr (hr, "Could not release DirectSoundCapture\n"); } s->dsound_capture = NULL;}static void *dsound_audio_init (void){ int err; HRESULT hr; dsound *s = &glob_dsound; hr = CoInitialize (NULL); if (FAILED (hr)) { dsound_logerr (hr, "Could not initialize COM\n"); return NULL; } hr = CoCreateInstance ( &CLSID_DirectSound, NULL, CLSCTX_ALL, &IID_IDirectSound, (void **) &s->dsound ); if (FAILED (hr)) { dsound_logerr (hr, "Could not create DirectSound instance\n"); return NULL; } hr = IDirectSound_Initialize (s->dsound, NULL); if (FAILED (hr)) { dsound_logerr (hr, "Could not initialize DirectSound\n"); hr = IDirectSound_Release (s->dsound); if (FAILED (hr)) { dsound_logerr (hr, "Could not release DirectSound\n"); } s->dsound = NULL; return NULL; } hr = CoCreateInstance ( &CLSID_DirectSoundCapture, NULL, CLSCTX_ALL, &IID_IDirectSoundCapture, (void **) &s->dsound_capture ); if (FAILED (hr)) { dsound_logerr (hr, "Could not create DirectSoundCapture instance\n"); } else { hr = IDirectSoundCapture_Initialize (s->dsound_capture, NULL); if (FAILED (hr)) { dsound_logerr (hr, "Could not initialize DirectSoundCapture\n"); hr = IDirectSoundCapture_Release (s->dsound_capture); if (FAILED (hr)) { dsound_logerr (hr, "Could not release DirectSoundCapture\n"); } s->dsound_capture = NULL; } } err = dsound_open (s); if (err) { dsound_audio_fini (s); return NULL; } return s;}static struct audio_option dsound_options[] = { {"LOCK_RETRIES", AUD_OPT_INT, &conf.lock_retries, "Number of times to attempt locking the buffer", NULL, 0}, {"RESTOURE_RETRIES", AUD_OPT_INT, &conf.restore_retries, "Number of times to attempt restoring the buffer", NULL, 0}, {"GETSTATUS_RETRIES", AUD_OPT_INT, &conf.getstatus_retries, "Number of times to attempt getting status of the buffer", NULL, 0}, {"SET_PRIMARY", AUD_OPT_BOOL, &conf.set_primary, "Set the parameters of primary buffer", NULL, 0}, {"LATENCY_MILLIS", AUD_OPT_INT, &conf.latency_millis, "(undocumented)", NULL, 0}, {"PRIMARY_FREQ", AUD_OPT_INT, &conf.settings.freq, "Primary buffer frequency", NULL, 0}, {"PRIMARY_CHANNELS", AUD_OPT_INT, &conf.settings.nchannels, "Primary buffer number of channels (1 - mono, 2 - stereo)", NULL, 0}, {"PRIMARY_FMT", AUD_OPT_FMT, &conf.settings.fmt, "Primary buffer format", NULL, 0}, {"BUFSIZE_OUT", AUD_OPT_INT, &conf.bufsize_out, "(undocumented)", NULL, 0}, {"BUFSIZE_IN", AUD_OPT_INT, &conf.bufsize_in, "(undocumented)", NULL, 0}, {NULL, 0, NULL, NULL, NULL, 0}};static struct audio_pcm_ops dsound_pcm_ops = { dsound_init_out, dsound_fini_out, dsound_run_out, dsound_write, dsound_ctl_out, dsound_init_in, dsound_fini_in, dsound_run_in, dsound_read, dsound_ctl_in};struct audio_driver dsound_audio_driver = { INIT_FIELD (name = ) "dsound", INIT_FIELD (descr = ) "DirectSound http://wikipedia.org/wiki/DirectSound", INIT_FIELD (options = ) dsound_options, INIT_FIELD (init = ) dsound_audio_init, INIT_FIELD (fini = ) dsound_audio_fini, INIT_FIELD (pcm_ops = ) &dsound_pcm_ops, INIT_FIELD (can_be_default = ) 1, INIT_FIELD (max_voices_out = ) INT_MAX, INIT_FIELD (max_voices_in = ) 1, INIT_FIELD (voice_size_out = ) sizeof (DSoundVoiceOut), INIT_FIELD (voice_size_in = ) sizeof (DSoundVoiceIn)};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -