Logo Search packages:      
Sourcecode: baycomusb version File versions  Download package

audiowin32.c

/*****************************************************************************/

/*
 *      audiowin32.c  --  Audio processing for "virtual transceiver", win32 IO.
 *
 *      Copyright (C) 1999, 2001  Thomas Sailer (t.sailer@alumni.ethz.ch)
 *
 *      This program is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
 *      the Free Software Foundation; either version 2 of the License, or
 *      (at your option) any later version.
 *
 *      This program is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 *
 *      You should have received a copy of the GNU General Public License
 *      along with this program; if not, write to the Free Software
 *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *  Please note that the GPL allows you to use the driver, NOT the radio.
 *  In order to use the radio, you need a license from the communications
 *  authority of your country.
 *
 */

/*****************************************************************************/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

/* AIX requires this to be the first thing in the file.  */
#ifndef __GNUC__
# if HAVE_ALLOCA_H
#  include <alloca.h>
# else
#  ifdef _AIX
#pragma alloca
#  else
#   ifndef alloca /* predefined by HP cc +Olibcalls */
char *alloca ();
#   endif
#  endif
# endif
#endif

#include <windows.h>
#include <mmsystem.h>
#include <malloc.h>
#include <cguid.h>

#include "trx.h"
#include "trxapi.h"

/* ---------------------------------------------------------------------- */

#define BUFSIZE    8192   /* must be significantly bigger than SNDLATENCY! */

#define WAVE_FORMAT_1M08 1
#define WAVE_FORMAT_1S08 2
#define WAVE_FORMAT_1M16 4
#define WAVE_FORMAT_1S16 8
#define WAVE_FORMAT_2M08 16
#define WAVE_FORMAT_2S08 32
#define WAVE_FORMAT_2M16 64
#define WAVE_FORMAT_2S16 128
#define WAVE_FORMAT_4M08 256
#define WAVE_FORMAT_4S08 512
#define WAVE_FORMAT_4M16 1024
#define WAVE_FORMAT_4S16 2048
#define WAVE_FORMAT_PCM 1

/* ---------------------------------------------------------------------- */

#if defined(HAVE_DIRECTX)

#include <directx.h>

struct dsdrivers {
      struct list_head list;
        GUID guid;
        char name[64];
      char desc[64];
};

static LIST_HEAD(dsplaylist);
static LIST_HEAD(dscapturelist);

/* ---------------------------------------------------------------------- */

static void stop(struct trx_thread_state *state)
{
      if (state->du.a.io.dsplay) {
            IDirectSoundBuffer_Stop(state->du.a.io.playbuf);
            IDirectSoundBuffer_Release(state->du.a.io.playbuf);
      }
      if (state->du.a.io.dsrec) {
            IDirectSoundCaptureBuffer_Stop(state->du.a.io.recbuf);
            IDirectSoundCaptureBuffer_Release(state->du.a.io.recbuf);
            IDirectSoundCapture_Release(state->du.a.io.dsrec);
      }
      if (state->du.a.io.dsplay)
            IDirectSound_Release(state->du.a.io.dsplay);
      state->du.a.io.recbuf = NULL;
      state->du.a.io.dsrec = NULL;
      state->du.a.io.playbuf = NULL;
      state->du.a.io.dsplay = NULL;
}

static void start(struct trx_thread_state *state)
{
      struct list_head *list;
      struct dsdrivers *drv;
        LPGUID lpguid;
        HRESULT res;
        WAVEFORMATEX waveformat;
        DSBUFFERDESC bdesc;
        DSCBUFFERDESC cbdesc;
        DSCAPS caps;
        DSCCAPS ccaps;
        DSBCAPS bcaps;
        DSCBCAPS cbcaps;
        unsigned int isprimary = 0, weight = ~0;
        void *lptr1;
        DWORD lbytes1;
        HWND hwnd = GetDesktopWindow();

      lpguid = NULL;
      for (list = dsplaylist.next; list != &dsplaylist; list = list->next) {
            drv = list_entry(list, struct dsdrivers, list);
            if (strcmp(drv->desc, state->cfg.adapt.audiodevout))
                  continue;
            if (memcmp(&drv->guid, &GUID_NULL, sizeof(drv->guid)))
                  lpguid = &drv->guid;
            break;
      }
      if (FAILED(res = DirectSoundCreate(lpguid, &state->du.a.io.dsplay, NULL))) {
            lprintf(1, "DirectSoundCreate error 0x%lx\n", res);
            goto errdscreate;
      }
      if (FAILED(res = IDirectSound_SetCooperativeLevel(state->du.a.io.dsplay, hwnd, DSSCL_WRITEPRIMARY))) {
            lprintf(3, "SetCooperativeLevel DSSCL_WRITEPRIMARY error 0x%lx\n", res);
            if (FAILED(res = IDirectSound_SetCooperativeLevel(state->du.a.io.dsplay, hwnd, DSSCL_EXCLUSIVE))) {
                  lprintf(1, "SetCooperativeLevel DSSCL_EXCLUSIVE error 0x%lx\n", res);
                  goto errdsb;
            }
      } else
            isprimary = 1;
      lpguid = NULL;
      for (list = dscapturelist.next; list != &dscapturelist; list = list->next) {
            drv = list_entry(list, struct dsdrivers, list);
            if (strcmp(drv->desc, state->cfg.adapt.audiodevin))
                  continue;
            if (memcmp(&drv->guid, &GUID_NULL, sizeof(drv->guid)))
                  lpguid = &drv->guid;
            break;
      }
      if (FAILED(res = DirectSoundCaptureCreate(lpguid, &state->du.a.io.dsrec, NULL))) {
            lprintf(1, "DirectSoundCaptureCreate error 0x%lx\n", res);
            goto errdsb;
      }
      /* DirectSound capabilities */
      caps.dwSize = sizeof(caps);
      if (FAILED(res = IDirectSound_GetCaps(state->du.a.io.dsplay, &caps))) {
            lprintf(1, "DirectSoundGetCaps error 0x%lx\n", res);
            goto errdscb;
      }
      lprintf(5, "DirectSound capabilities:\n"
            "  Flags 0x%04lx\n"
            "  SampleRate min %lu max %lu\n"
            "  # Primary Buffers %lu\n",
            caps.dwFlags, caps.dwMinSecondarySampleRate, caps.dwMaxSecondarySampleRate, caps.dwPrimaryBuffers);
        /* DirectSoundCapture capabilities */
      ccaps.dwSize = sizeof(ccaps);
      if (FAILED(res = IDirectSoundCapture_GetCaps(state->du.a.io.dsrec, &ccaps))) {
            lprintf(1, "DirectSoundCaptureGetCaps error 0x%lx\n", res);
            goto errdscb;
      }
      lprintf(5, "DirectSoundCapture capabilities:\n"
            "  Flags 0x%04lx\n"
            "  Formats 0x%04lx\n"
            "  Channels %lu\n",
            ccaps.dwFlags, ccaps.dwFormats, ccaps.dwChannels);
        /* adjust sampling rate */
      if (!(caps.dwFlags & DSCAPS_PRIMARY16BIT) || !(caps.dwFlags & DSCAPS_PRIMARYMONO)) {
            lprintf(1, "Unsupported playback format 16bit mono\n");
            goto errdscb;
      }
      if (state->du.a.p.sratedspout < caps.dwMinSecondarySampleRate)
            state->du.a.p.sratedspout = caps.dwMinSecondarySampleRate;
      if (state->du.a.p.sratedspout > caps.dwMaxSecondarySampleRate)
            state->du.a.p.sratedspout = caps.dwMaxSecondarySampleRate;
      if ((ccaps.dwFormats & WAVE_FORMAT_1M16) && abs(state->du.a.p.srateusb - 11025) < weight) {
            weight = abs(state->du.a.p.srateusb - 11025);
            state->du.a.p.sratedspin = 11025;
      }
      if ((ccaps.dwFormats & WAVE_FORMAT_1M16) && abs(state->du.a.p.srateusb - 22050) < weight) {
            weight = abs(state->du.a.p.srateusb - 22050);
            state->du.a.p.sratedspin = 22050;
      }
      if ((ccaps.dwFormats & WAVE_FORMAT_1M16) && abs(state->du.a.p.srateusb - 44100) < weight) {
            weight = abs(state->du.a.p.srateusb - 44100);
            state->du.a.p.sratedspin = 44100;
      }
      if (weight == ~0) {
            lprintf(1, "Unsupported capture sampling rate\n");
            goto errdscb;
      }
        /* create capture buffer */
      memset(&waveformat, 0, sizeof(waveformat));
      waveformat.wFormatTag = WAVE_FORMAT_PCM;
      waveformat.wBitsPerSample = 16;
      waveformat.nChannels = 1;
      waveformat.nSamplesPerSec = state->du.a.p.sratedspin;
      waveformat.nBlockAlign = waveformat.nChannels * waveformat.wBitsPerSample / 8;
      waveformat.nAvgBytesPerSec = waveformat.nSamplesPerSec * waveformat.nBlockAlign;
      memset(&cbdesc, 0, sizeof(cbdesc));
      cbdesc.dwSize = sizeof(cbdesc);
      cbdesc.dwFlags = /* DSCBCAPS_WAVEMAPPED */ 0;
      cbdesc.dwBufferBytes = 65536;
      cbdesc.lpwfxFormat = &waveformat;
      if (FAILED(res = IDirectSoundCapture_CreateCaptureBuffer(state->du.a.io.dsrec, &cbdesc, &state->du.a.io.recbuf, NULL))) {
            lprintf(1, "CreateSoundCaptureBuffer error 0x%lx\n", res);
            goto errdscb;
      }
        /* create playback buffer */
      if (isprimary) {
            memset(&bdesc, 0, sizeof(bdesc));
            bdesc.dwSize = sizeof(bdesc);
            bdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_PRIMARYBUFFER;
            bdesc.dwBufferBytes = 0;
            bdesc.lpwfxFormat = NULL;
            if (FAILED(res = IDirectSound_CreateSoundBuffer(state->du.a.io.dsplay, &bdesc, &state->du.a.io.playbuf, NULL))) {
                  lprintf(1, "DirectSoundCreateSoundBuffer error 0x%lx\n", res);
                  goto errdspb;
            }
            memset(&waveformat, 0, sizeof(waveformat));
            waveformat.wFormatTag = WAVE_FORMAT_PCM;
            waveformat.wBitsPerSample = 16;
            waveformat.nChannels = 1;
            waveformat.nSamplesPerSec = state->du.a.p.sratedspout;
            waveformat.nBlockAlign = waveformat.nChannels * waveformat.wBitsPerSample / 8;
            waveformat.nAvgBytesPerSec = waveformat.nSamplesPerSec * waveformat.nBlockAlign;
            if (FAILED(res = IDirectSoundBuffer_SetFormat(state->du.a.io.playbuf, &waveformat))) {
                  lprintf(1, "DirectSoundBufferSetFormat error 0x%lx\n", res);
                  goto errsnd;
            }
            if (FAILED(res = IDirectSoundBuffer_GetFormat(state->du.a.io.playbuf, &waveformat, sizeof(waveformat), NULL))) {
                  lprintf(1, "DirectSoundBufferGetFormat error 0x%lx\n", res);
                  goto errsnd;
            }
            lprintf(5, "Sampling rates: Recording %u Playback %u\n", state->du.a.p.sratedspin, state->du.a.p.sratedspout);
      } else {
            /* first try to set the format of the primary buffer */
            memset(&bdesc, 0, sizeof(bdesc));
            bdesc.dwSize = sizeof(bdesc);
            bdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_PRIMARYBUFFER;
            bdesc.dwBufferBytes = 0;
            bdesc.lpwfxFormat = NULL;
            if (FAILED(res = IDirectSound_CreateSoundBuffer(state->du.a.io.dsplay, &bdesc, &state->du.a.io.playbuf, NULL))) {
                  lprintf(1, "DirectSoundCreateSoundBuffer (primary) error 0x%lx\n", res);
            } else {
                  memset(&waveformat, 0, sizeof(waveformat));
                  waveformat.wFormatTag = WAVE_FORMAT_PCM;
                  waveformat.wBitsPerSample = 16;
                  waveformat.nChannels = 1;
                  waveformat.nSamplesPerSec = state->du.a.p.sratedspout;
                  waveformat.nBlockAlign = waveformat.nChannels * waveformat.wBitsPerSample / 8;
                  waveformat.nAvgBytesPerSec = waveformat.nSamplesPerSec * waveformat.nBlockAlign;
                  if (FAILED(res = IDirectSoundBuffer_SetFormat(state->du.a.io.playbuf, &waveformat))) {
                        lprintf(1, "DirectSoundBufferSetFormat (primary) error 0x%lx\n", res);
                  }
                  IDirectSoundBuffer_Release(state->du.a.io.playbuf);        
            }
            /* create secondary */
            memset(&waveformat, 0, sizeof(waveformat));
            waveformat.wFormatTag = WAVE_FORMAT_PCM;
            waveformat.wBitsPerSample = 16;
            waveformat.nChannels = 1;
            waveformat.nSamplesPerSec = state->du.a.p.sratedspout;
            waveformat.nBlockAlign = waveformat.nChannels * waveformat.wBitsPerSample / 8;
            waveformat.nAvgBytesPerSec = waveformat.nSamplesPerSec * waveformat.nBlockAlign;
            memset(&bdesc, 0, sizeof(bdesc));
            bdesc.dwSize = sizeof(bdesc);
            bdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_GLOBALFOCUS;
            bdesc.dwBufferBytes = 65536;
            bdesc.lpwfxFormat = &waveformat;
            if (FAILED(res = IDirectSound_CreateSoundBuffer(state->du.a.io.dsplay, &bdesc, &state->du.a.io.playbuf, NULL))) {
                  lprintf(1, "DirectSoundCreateSoundBuffer error 0x%lx\n", res);
                  goto errdspb;
            }
      }
         /* find out buffer size */
      bcaps.dwSize = sizeof(bcaps);
      if (FAILED(res = IDirectSoundBuffer_GetCaps(state->du.a.io.playbuf, &bcaps))) {
            lprintf(1, "DirectSoundBufferGetCaps error 0x%lx\n", res);
            goto errsnd;
      }
      lprintf(1, "Playback buffer characteristics:\n"
            "  Flags 0x%04lx\n"
            "  Buffer Bytes %lu\n"
            "  Unlock Transfer rate %lu\n"
            "  CPU overhead %lu\n",
            bcaps.dwFlags, bcaps.dwBufferBytes, bcaps.dwUnlockTransferRate, bcaps.dwPlayCpuOverhead);
      state->du.a.io.playbufsz = bcaps.dwBufferBytes;
      cbcaps.dwSize = sizeof(cbcaps);
      if (FAILED(res = IDirectSoundCaptureBuffer_GetCaps(state->du.a.io.recbuf, &cbcaps))) {
            lprintf(1, "DirectSoundCaptureBufferGetCaps error 0x%lx\n", res);
            goto errsnd;
      }
      lprintf(5, "Recording buffer characteristics:\n"
            "  Flags 0x%04lx\n"
            "  Buffer Bytes %lu\n",
            cbcaps.dwFlags, cbcaps.dwBufferBytes);
      state->du.a.io.recbufsz = cbcaps.dwBufferBytes;
        /* start recording */
      if (FAILED(res = IDirectSoundCaptureBuffer_Start(state->du.a.io.recbuf, DSCBSTART_LOOPING))) {
            lprintf(1, "DirectSoundCaptureBufferStart error 0x%lx\n", res);
            goto errsnd;
      }
        /* zero playback buffer and start it */
      if (FAILED(res = IDirectSoundBuffer_Lock(state->du.a.io.playbuf, 0, state->du.a.io.playbufsz, &lptr1, &lbytes1, NULL, NULL, 0))) {
            if (res != DSERR_BUFFERLOST) {
                  lprintf(1, "DirectSoundBufferLock error 0x%lx\n", res);
                  goto errsnd;
            }
            if (FAILED(res = IDirectSoundBuffer_Restore(state->du.a.io.playbuf))) {
                  lprintf(1, "DirectSoundBufferRestore error 0x%lx\n", res);
                  goto errsnd;
            }
            if (FAILED(res = IDirectSoundBuffer_Lock(state->du.a.io.playbuf, 0, state->du.a.io.playbufsz, &lptr1, &lbytes1, NULL, NULL, 0))) {
                  lprintf(1, "DirectSoundBufferLock error 0x%lx\n", res);
                  goto errsnd;
            }
      }
      memset(lptr1, 0, lbytes1);
      if (FAILED(res = IDirectSoundBuffer_Unlock(state->du.a.io.playbuf, lptr1, lbytes1, NULL, 0))) {
            lprintf(1, "DirectSoundBufferUnlock error 0x%lx\n", res);
            goto errsnd;
      }
      if (FAILED(res = IDirectSoundBuffer_Play(state->du.a.io.playbuf, 0, 0, DSBPLAY_LOOPING))) {
            lprintf(1, "DirectSoundBufferPlay error 0x%lx\n", res);
            goto errsnd;
      }
      state->du.a.io.playptr = 2*SNDLATENCY;
      state->du.a.io.recptr = state->du.a.io.recbufsz - 2*SNDLATENCY;
        return;

  errsnd:
      IDirectSoundBuffer_Stop(state->du.a.io.playbuf);
      IDirectSoundBuffer_Release(state->du.a.io.playbuf);
  errdspb:
      IDirectSoundCaptureBuffer_Stop(state->du.a.io.recbuf);
      IDirectSoundCaptureBuffer_Release(state->du.a.io.recbuf);
  errdscb:      
      IDirectSoundCapture_Release(state->du.a.io.dsrec);
  errdsb:
      IDirectSound_Release(state->du.a.io.dsplay);
  errdscreate:
      state->du.a.io.recbuf = NULL;
      state->du.a.io.dsrec = NULL;
      state->du.a.io.playbuf = NULL;
      state->du.a.io.dsplay = NULL;
      state->du.a.p.sratedspin = state->du.a.p.sratedspout = state->du.a.p.srateusb;
}

/* ---------------------------------------------------------------------- */

void audio_open(struct trx_thread_state *state)
{
      state->du.a.io.dsplay = NULL;
      state->du.a.io.dsrec = NULL;
      state->du.a.io.playbuf = NULL;
      state->du.a.io.recbuf = NULL;
      state->du.a.io.playptr = 0;
      state->du.a.io.recptr = 0;
      state->du.a.p.srateusb = state->du.a.p.sratedspin = state->du.a.p.sratedspout = AUDIOSAMPLINGRATE;
      start(state);
      audioproc_init(state);
}

void audio_close(struct trx_thread_state *state)
{
      stop(state);
}

void audio_input(struct trx_thread_state *state, const signed char *samples, unsigned int nrsamples)
{
      int16_t sbuf[BUFSIZE];
      HRESULT res;
      DWORD lockbytes1, lockbytes2, delay;
      int16_t *sptr1;
      int16_t *sptr2;
      int cnt;

      /* usb->dsp direction */
      /* get FIFO count */
      cnt = audioproc_convertoutput(state, nrsamples, samples, sbuf);
      if (!state->du.a.io.playbuf)
            return;
      if (FAILED(res = IDirectSoundBuffer_Lock(state->du.a.io.playbuf, state->du.a.io.playptr, cnt*2, 
                                     (LPVOID)&sptr1, &lockbytes1,
                                     (LPVOID)&sptr2, &lockbytes2, 0))) {
            lprintf(0, "IDirectSoundBuffer_Lock error %lu\n", res);
            goto err;
      }
      memcpy(sptr1, sbuf, lockbytes1);
      if (lockbytes1 < cnt*sizeof(sbuf[0]))
            memcpy(sptr2, sbuf + lockbytes1/sizeof(sbuf[0]), cnt*sizeof(sbuf[0]) - lockbytes1);
      if (FAILED(res = IDirectSoundBuffer_Unlock(state->du.a.io.playbuf, sptr1, lockbytes1, sptr2, lockbytes2))) {
            lprintf(0, "IDirectSoundBuffer_Unlock error %lu\n", res);
            goto err;
      }
      state->du.a.io.playptr = (state->du.a.io.playptr + cnt*sizeof(sbuf[0])) % state->du.a.io.playbufsz;
      /* get output delay */
      if (FAILED(res = IDirectSoundBuffer_GetCurrentPosition(state->du.a.io.playbuf, &delay, NULL))) {
            lprintf(0, "IDirectSoundBuffer_GetCurrentPosition error %lu\n", res);
            goto err;
      }
      delay = (state->du.a.io.playbufsz + state->du.a.io.playptr - delay) % state->du.a.io.playbufsz;
      delay /= sizeof(sbuf[0]);
      /* adjust speed */
      if (audioproc_adjustoutput(state, delay))
            goto err;
      return;

err:
      stop(state);
}

void audio_output(struct trx_thread_state *state, signed char *samples, unsigned int nrsamples)
{
      int16_t *sbuf;
      HRESULT res;
      DWORD lockbytes1, lockbytes2, delay;
      int16_t *sptr1;
      int16_t *sptr2;
      unsigned int isamples, ocnts;

      /* dsp->usb direction */
      if (!nrsamples)
            return;
      if (!state->du.a.io.recbuf) {
            isamples = audioproc_convertinput_isamples(state, nrsamples);
            sbuf = alloca(isamples * sizeof(sbuf[0]));
            memset(sbuf, 0, isamples * sizeof(sbuf[0]));
            audioproc_convertinput(state, isamples, nrsamples, sbuf, samples);
            return;
      }
      isamples = audioproc_convertinput_isamples(state, nrsamples);
      sbuf = alloca(isamples * sizeof(sbuf[0]));
      if (FAILED(res = IDirectSoundCaptureBuffer_Lock(state->du.a.io.recbuf, state->du.a.io.recptr, isamples * sizeof(sbuf[0]), 
                                          (LPVOID)&sptr1, &lockbytes1,
                                          (LPVOID)&sptr2, &lockbytes2, 0))) {
            lprintf(0, "IDirectSoundCaptureBuffer_Lock error %lu\n", res);
            goto err;
      }
      memcpy(sbuf, sptr1, lockbytes1);
      if (lockbytes1 < isamples * sizeof(sbuf[0]))
            memcpy(sbuf+lockbytes1/sizeof(sbuf[0]), sptr2, isamples * sizeof(sbuf[0]) - lockbytes1);
      if (FAILED(res = IDirectSoundCaptureBuffer_Unlock(state->du.a.io.recbuf, sptr1, lockbytes1, sptr2, lockbytes2))) {
            lprintf(0, "IDirectSoundCaptureBuffer_Unlock error %lu\n", res);
            goto err;
      }
      state->du.a.io.recptr = (state->du.a.io.recptr + isamples * sizeof(sbuf[0])) % state->du.a.io.recbufsz;
      audioproc_convertinput(state, isamples, nrsamples, sbuf, samples);
      if (FAILED(res = IDirectSoundCaptureBuffer_GetCurrentPosition(state->du.a.io.recbuf, &delay, NULL))) {
            lprintf(0, "IDirectSoundCaptureBuffer_GetCurrentPosition error %lu\n", res);
            goto err;
      }
      ocnts = (state->du.a.io.recbufsz + delay - state->du.a.io.recptr) % state->du.a.io.recbufsz;
      ocnts /= sizeof(sbuf[0]);
      /* adjust speed */
      if (audioproc_adjustinput(state, ocnts))
            goto err;
      return;

err:
      stop(state);
}

/* ---------------------------------------------------------------------- */

static BOOL CALLBACK DSEnumProc(LPGUID guid, LPCSTR lpszDesc, LPCSTR lpszDrvName, LPVOID lpcontext)
{
      struct list_head *list = lpcontext;
        struct dsdrivers *drv;
 
      if (!(drv = malloc(sizeof(struct dsdrivers)))) {
            lprintf(1, "DSEnumProc: out of memory\n");
            return TRUE;
      }
        if (guid)
                drv->guid = *guid;
        else
                drv->guid = GUID_NULL;
      if (!lpszDrvName)
            drv->name[0] = 0;
      else
            strncpy(drv->name, lpszDrvName, sizeof(drv->name));
      strncpy(drv->desc, lpszDesc, sizeof(drv->desc));
      drv->name[sizeof(drv->name)-1] = 0;
      drv->desc[sizeof(drv->desc)-1] = 0;
      list_add_tail(&drv->list, list);
        lprintf(1, "has %sGUID, desc %s drvname %s\n", guid ? "" : "no ", lpszDesc, lpszDrvName ? lpszDrvName : "(null)");
        return TRUE;
}

void audio_globalinit(void)
{
        lprintf(1, "DirectSound drivers\n");
        DirectSoundEnumerateA(DSEnumProc, &dsplaylist);
        lprintf(1, "DirectSoundCapture drivers\n");
        DirectSoundCaptureEnumerateA(DSEnumProc, &dscapturelist);
}

struct trxapi_baycomusb_adapter_audio_devs *audio_get_device_list(void)
{
      struct trxapi_baycomusb_adapter_audio_devs *ad;
      unsigned int nrdevin = 0, nrdevout = 0;
      struct list_head *list;
      struct dsdrivers *drv;
      unsigned int i;

      for (list = dscapturelist.next; list != &dscapturelist; list = list->next)
            nrdevin++;
      for (list = dsplaylist.next; list != &dsplaylist; list = list->next)
            nrdevout++;
      /* retrieve audio devs */
      if (!(ad = calloc(1, sizeof(struct trxapi_baycomusb_adapter_audio_devs) + 
                    nrdevin * sizeof(trxapi_audiodevice_t) + 
                    nrdevout * sizeof(trxapi_audiodevice_t))))
            return NULL;
      ad->audiodevsin = (void *)(ad + 1);
      ad->nraudiodevsin = nrdevin;
      ad->audiodevsout = &ad->audiodevsin[nrdevin];
      ad->nraudiodevsout = nrdevout;
      for (list = dscapturelist.next, i = 0; i < nrdevin; i++, list = list->next) {
            drv = list_entry(list, struct dsdrivers, list);
            strncpy(ad->audiodevsin[i], drv->desc, sizeof(ad->audiodevsin[i]));
            ad->audiodevsin[i][sizeof(ad->audiodevsin[i])-1] = 0;
      }
      for (list = dsplaylist.next, i = 0; i < nrdevout; i++, list = list->next) {
            drv = list_entry(list, struct dsdrivers, list);
            strncpy(ad->audiodevsout[i], drv->desc, sizeof(ad->audiodevsout[i]));
            ad->audiodevsout[i][sizeof(ad->audiodevsout[i])-1] = 0;
      }
      return ad;
}

/* ---------------------------------------------------------------------- */
#else /* !HAVE_DIRECTX */

void audio_globalinit(void)
{
}

struct trxapi_baycomusb_adapter_audio_devs *audio_get_device_list(void)
{
      return NULL;
}

void audio_open(struct trx_thread_state *state)
{
      state->du.a.p.srateusb = state->du.a.p.sratedspin = state->du.a.p.sratedspout = AUDIOSAMPLINGRATE;
      audioproc_init(state);
}

void audio_close(struct trx_thread_state *state)
{
}

void audio_input(struct trx_thread_state *state, const signed char *samples, unsigned int nrsamples)
{
      audioproc_convertoutput(state, nrsamples, samples, sbuf);
}

void audio_output(struct trx_thread_state *state, signed char *samples, unsigned int nrsamples)
{
      int16_t *sbuf;
      unsigned int isamples;

      if (!nrsamples)
            return;
      isamples = audioproc_convertinput_isamples(state, nrsamples);
      sbuf = alloca(isamples * sizeof(sbuf[0]));
      memset(sbuf, 0, isamples * sizeof(sbuf[0]));
      audioproc_convertinput(state, isamples, nrsamples, sbuf, samples);
}

/* ---------------------------------------------------------------------- */
#endif /* HAVE_DIRECTX */

Generated by  Doxygen 1.6.0   Back to index