Ejemplo n.º 1
0
int jack_send_dacs(void)
{
    t_sample * fp;
    int j;
    int rtnval =  SENDDACS_YES;
    int timenow;
    int timeref = sys_getrealtime();
    if (!jack_client) return SENDDACS_NO;
    if (!sys_inchannels && !sys_outchannels) return (SENDDACS_NO);
    if (jack_dio_error)
    {
        sys_log_error(ERR_RESYNC);
        jack_dio_error = 0;
    }
    pthread_mutex_lock(&jack_mutex);
    if (jack_filled >= jack_out_max)
        pthread_cond_wait(&jack_sem,&jack_mutex);

    if (!jack_client)
    {
        pthread_mutex_unlock(&jack_mutex);
        return SENDDACS_NO;
    }
    jack_started = 1;

    fp = sys_soundout;
    for (j = 0; j < sys_outchannels; j++)
    {
        memcpy(jack_outbuf + (j * BUF_JACK) + jack_filled, fp,
            DEFDACBLKSIZE*sizeof(t_sample));
        fp += DEFDACBLKSIZE;
    }
    fp = sys_soundin;
    for (j = 0; j < sys_inchannels; j++)
    {
        memcpy(fp, jack_inbuf + (j * BUF_JACK) + jack_filled,
            DEFDACBLKSIZE*sizeof(t_sample));
        fp += DEFDACBLKSIZE;
    }
    jack_filled += DEFDACBLKSIZE;
    pthread_mutex_unlock(&jack_mutex);

    if ((timenow = sys_getrealtime()) - timeref > 0.002)
    {
        rtnval = SENDDACS_SLEPT;
    }
    memset(sys_soundout, 0, DEFDACBLKSIZE*sizeof(t_sample)*sys_outchannels);
    return rtnval;
}
Ejemplo n.º 2
0
void sys_set_audio_settings(int naudioindev, int *audioindev, int nchindev,
    int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev,
    int *choutdev, int rate, int advance, int callback, int blocksize)
{
    int i;
    int defaultchannels = SYS_DEFAULTCH;
    int inchans, outchans, nrealindev, nrealoutdev;
    int realindev[MAXAUDIOINDEV], realoutdev[MAXAUDIOOUTDEV];
    int realinchans[MAXAUDIOINDEV], realoutchans[MAXAUDIOOUTDEV];

    char indevlist[MAXNDEV*DEVDESCSIZE], outdevlist[MAXNDEV*DEVDESCSIZE];
    int indevs = 0, outdevs = 0, canmulti = 0, cancallback = 0;

    /* initialize device-arrays */
    for(i=0; i<MAXAUDIOINDEV; i++)
        realindev[i]  = realinchans[i]  = 0;
    for(i=0; i<MAXAUDIOOUTDEV; i++)
        realoutdev[i] = realoutchans[i] = 0;
    for(i=0; i<MAXNDEV*DEVDESCSIZE; i++)
        indevlist[i]  = outdevlist[i]   = 0;

    audio_getdevs(indevlist, &indevs, outdevlist, &outdevs, &canmulti,
        &cancallback, MAXNDEV, DEVDESCSIZE);

    if (rate < 1)
        rate = DEFAULTSRATE;
    if (advance < 0)
        advance = DEFAULTADVANCE;
    if (blocksize != (1 << ilog2(blocksize)) || blocksize < DEFDACBLKSIZE)
        blocksize = DEFDACBLKSIZE;
     audio_init();
        /* Since the channel vector might be longer than the
        audio device vector, or vice versa, we fill the shorter one
        in to match the longer one.  Also, if both are empty, we fill in
        one device (the default) and two channels. */
    if (naudioindev == -1)
    {           /* no input audio devices specified */
        if (nchindev == -1)
        {
            if (indevs >= 1)
            {
                nchindev=1;
                chindev[0] = defaultchannels;
                naudioindev = 1;
                audioindev[0] = DEFAULTAUDIODEV;
            }
            else naudioindev = nchindev = 0;
        }
        else
        {
            for (i = 0; i < MAXAUDIOINDEV; i++)
                audioindev[i] = i;
            naudioindev = nchindev;
        }
    }
    else
    {
        if (nchindev == -1)
        {
            nchindev = naudioindev;
            for (i = 0; i < naudioindev; i++)
                chindev[i] = defaultchannels;
        }
        else if (nchindev > naudioindev)
        {
            for (i = naudioindev; i < nchindev; i++)
            {
                if (i == 0)
                    audioindev[0] = DEFAULTAUDIODEV;
                else audioindev[i] = audioindev[i-1] + 1;
            }
            naudioindev = nchindev;
        }
        else if (nchindev < naudioindev)
        {
            for (i = nchindev; i < naudioindev; i++)
            {
                if (i == 0)
                    chindev[0] = defaultchannels;
                else chindev[i] = chindev[i-1];
            }
            naudioindev = nchindev;
        }
    }

    if (naudiooutdev == -1)
    {           /* not set */
        if (nchoutdev == -1)
        {
            if (outdevs >= 1)
            {
                nchoutdev=1;
                choutdev[0]=defaultchannels;
                naudiooutdev=1;
                audiooutdev[0] = DEFAULTAUDIODEV;
            }
            else nchoutdev = naudiooutdev = 0;
        }
        else
        {
            for (i = 0; i < MAXAUDIOOUTDEV; i++)
                audiooutdev[i] = i;
            naudiooutdev = nchoutdev;
        }
    }
    else
    {
        if (nchoutdev == -1)
        {
            nchoutdev = naudiooutdev;
            for (i = 0; i < naudiooutdev; i++)
                choutdev[i] = defaultchannels;
        }
        else if (nchoutdev > naudiooutdev)
        {
            for (i = naudiooutdev; i < nchoutdev; i++)
            {
                if (i == 0)
                    audiooutdev[0] = DEFAULTAUDIODEV;
                else audiooutdev[i] = audiooutdev[i-1] + 1;
            }
            naudiooutdev = nchoutdev;
        }
        else if (nchoutdev < naudiooutdev)
        {
            for (i = nchoutdev; i < naudiooutdev; i++)
            {
                if (i == 0)
                    choutdev[0] = defaultchannels;
                else choutdev[i] = choutdev[i-1];
            }
            naudiooutdev = nchoutdev;
        }
    }

        /* count total number of input and output channels */
    for (i = nrealindev = inchans = 0; i < naudioindev; i++)
        if (chindev[i] > 0)
    {
        realinchans[nrealindev] = chindev[i];
        realindev[nrealindev] = audioindev[i];
        inchans += chindev[i];
        nrealindev++;
    }
    for (i = nrealoutdev = outchans = 0; i < naudiooutdev; i++)
        if (choutdev[i] > 0)
    {
        realoutchans[nrealoutdev] = choutdev[i];
        realoutdev[nrealoutdev] = audiooutdev[i];
        outchans += choutdev[i];
        nrealoutdev++;
    }
    sys_schedadvance = advance * 1000;
    sys_log_error(ERR_NOTHING);
    audio_nextinchans = inchans;
    audio_nextoutchans = outchans;
    sys_setchsr(audio_nextinchans, audio_nextoutchans, rate);
    sys_save_audio_params(nrealindev, realindev, realinchans,
        nrealoutdev, realoutdev, realoutchans, rate, advance, callback,
            blocksize);
}
Ejemplo n.º 3
0
int alsa_send_dacs(void)
{
#ifdef DEBUG_ALSA_XFER
    static int xferno = 0;
    static int callno = 0;
#endif
    static double timenow;
    double timelast;
    t_sample *fp, *fp1, *fp2;
    int i, j, k, err, iodev, result, ch;
    int chansintogo, chansouttogo;
    unsigned int transfersize;

    if (alsa_usemmap)
        return (alsamm_send_dacs());

    if (!alsa_nindev && !alsa_noutdev)
        return (SENDDACS_NO);

    chansintogo = sys_inchannels;
    chansouttogo = sys_outchannels;
    transfersize = DEFDACBLKSIZE;

    timelast = timenow;
    timenow = sys_getrealtime();

#ifdef DEBUG_ALSA_XFER
    if (timenow - timelast > 0.050)
        fprintf(stderr, "(%d)",
                (int)(1000 * (timenow - timelast))), fflush(stderr);
    callno++;
#endif

    alsa_checkiosync();     /* check I/O are in sync and data not late */

    for (iodev = 0; iodev < alsa_nindev; iodev++)
    {
        snd_pcm_status(alsa_indev[iodev].a_handle, alsa_status);
        if (snd_pcm_status_get_avail(alsa_status) < transfersize)
            return SENDDACS_NO;
    }
    for (iodev = 0; iodev < alsa_noutdev; iodev++)
    {
        snd_pcm_status(alsa_outdev[iodev].a_handle, alsa_status);
        if (snd_pcm_status_get_avail(alsa_status) < transfersize)
            return SENDDACS_NO;
    }
    /* do output */
    for (iodev = 0, fp1 = sys_soundout, ch = 0; iodev < alsa_noutdev; iodev++)
    {
        int thisdevchans = alsa_outdev[iodev].a_channels;
        int chans = (chansouttogo < thisdevchans ? chansouttogo : thisdevchans);
        chansouttogo -= chans;

        if (alsa_outdev[iodev].a_sampwidth == 4)
        {
            for (i = 0; i < chans; i++, ch++, fp1 += DEFDACBLKSIZE)
                for (j = i, k = DEFDACBLKSIZE, fp2 = fp1; k--;
                        j += thisdevchans, fp2++)
                {
                    float s1 = *fp2 * INT32_MAX;
                    ((t_alsa_sample32 *)alsa_snd_buf)[j] = CLIP32(s1);
                }
            for (; i < thisdevchans; i++, ch++)
                for (j = i, k = DEFDACBLKSIZE; k--; j += thisdevchans)
                    ((t_alsa_sample32 *)alsa_snd_buf)[j] = 0;
        }
        else if (alsa_outdev[iodev].a_sampwidth == 3)
        {
            for (i = 0; i < chans; i++, ch++, fp1 += DEFDACBLKSIZE)
                for (j = i, k = DEFDACBLKSIZE, fp2 = fp1; k--;
                        j += thisdevchans, fp2++)
                {
                    int s = *fp2 * 8388352.;
                    if (s > 8388351)
                        s = 8388351;
                    else if (s < -8388351)
                        s = -8388351;
#if BYTE_ORDER == LITTLE_ENDIAN
                    ((char *)(alsa_snd_buf))[3*j] = (s & 255);
                    ((char *)(alsa_snd_buf))[3*j+1] = ((s>>8) & 255);
                    ((char *)(alsa_snd_buf))[3*j+2] = ((s>>16) & 255);
#else
                    fprintf(stderr("big endian 24-bit not supported");
#endif
                }
            for (; i < thisdevchans; i++, ch++)
                for (j = i, k = DEFDACBLKSIZE; k--; j += thisdevchans)
                    ((char *)(alsa_snd_buf))[3*j] =
                        ((char *)(alsa_snd_buf))[3*j+1] =
                            ((char *)(alsa_snd_buf))[3*j+2] = 0;
        }
        else        /* 16 bit samples */
        {
            for (i = 0; i < chans; i++, ch++, fp1 += DEFDACBLKSIZE)
                for (j = ch, k = DEFDACBLKSIZE, fp2 = fp1; k--;
                        j += thisdevchans, fp2++)
                {
                    int s = *fp2 * 32767.;
                    if (s > 32767)
                        s = 32767;
                    else if (s < -32767)
                        s = -32767;
                    ((t_alsa_sample16 *)alsa_snd_buf)[j] = s;
                }
            for (; i < thisdevchans; i++, ch++)
                for (j = ch, k = DEFDACBLKSIZE; k--; j += thisdevchans)
                    ((t_alsa_sample16 *)alsa_snd_buf)[j] = 0;
        }
        result = snd_pcm_writei(alsa_outdev[iodev].a_handle, alsa_snd_buf,
                                transfersize);

        if (result != (int)transfersize)
        {
#ifdef DEBUG_ALSA_XFER
            if (result >= 0 || errno == EAGAIN)
                fprintf(stderr, "ALSA: write returned %d of %d\n",
                        result, transfersize);
            else fprintf(stderr, "ALSA: write: %s\n",
                             snd_strerror(errno));
            fprintf(stderr,
                    "inputcount %d, outputcount %d, outbufsize %d\n",
                    inputcount, outputcount,
                    (ALSA_EXTRABUFFER + sys_advance_samples)
                    * alsa_outdev[iodev].a_sampwidth * outchannels);
#endif
            sys_log_error(ERR_DACSLEPT);
            return (SENDDACS_NO);
        }

        /* zero out the output buffer */
        memset(sys_soundout, 0, DEFDACBLKSIZE * sizeof(*sys_soundout) *
               sys_outchannels);
        if (sys_getrealtime() - timenow > 0.002)
        {
#ifdef DEBUG_ALSA_XFER
            fprintf(stderr, "output %d took %d msec\n",
                    callno, (int)(1000 * (timenow - timelast))), fflush(stderr);
#endif
            timenow = sys_getrealtime();
            sys_log_error(ERR_DACSLEPT);
        }
    }
Ejemplo n.º 4
0
int pa_send_dacs(void)
{
    t_sample *fp;
    float *fp2, *fp3;
    float *conversionbuf;
    int j, k;
    int rtnval =  SENDDACS_YES;
    int timenow;
    int timeref = sys_getrealtime();
    if (!sys_inchannels && !sys_outchannels)
        return (SENDDACS_NO); 
#if CHECKFIFOS
    if (sys_outchannels * sys_ringbuf_GetReadAvailable(&pa_inring) !=   
        sys_inchannels * sys_ringbuf_GetWriteAvailable(&pa_outring))
            fprintf(stderr, "warning (2): in and out rings unequal  (%d, %d)\n",
                sys_ringbuf_GetReadAvailable(&pa_inring),
                    sys_ringbuf_GetWriteAvailable(&pa_outring));
#endif
    conversionbuf = (float *)alloca((sys_inchannels > sys_outchannels?
        sys_inchannels:sys_outchannels) * DEFDACBLKSIZE * sizeof(float));
    if (pa_dio_error)
    {
        sys_log_error(ERR_RESYNC);
        pa_dio_error = 0;
    }

    if (!sys_inchannels)    /* if no input channels sync on output */
    {
#ifdef THREADSIGNAL
        pthread_mutex_lock(&pa_mutex);
#endif
        while (sys_ringbuf_GetWriteAvailable(&pa_outring) <
            (long)(sys_outchannels * DEFDACBLKSIZE * sizeof(float)))
#ifdef THREADSIGNAL
                pthread_cond_wait(&pa_sem, &pa_mutex);
#else
#ifdef _WIN32
                Sleep(1);
#else
                usleep(1000);
#endif /* _WIN32 */
#endif /* THREADSIGNAL */
#ifdef THREADSIGNAL
        pthread_mutex_unlock(&pa_mutex);
#endif
    }
        /* write output */
    if (sys_outchannels)
    {
        for (j = 0, fp = sys_soundout, fp2 = conversionbuf;
            j < sys_outchannels; j++, fp2++)
                for (k = 0, fp3 = fp2; k < DEFDACBLKSIZE;
                    k++, fp++, fp3 += sys_outchannels)
                        *fp3 = *fp;
        sys_ringbuf_Write(&pa_outring, conversionbuf,
            sys_outchannels*(DEFDACBLKSIZE*sizeof(float)));
    }
    if (sys_inchannels)    /* if there is input sync on it */
    {
#ifdef THREADSIGNAL
        pthread_mutex_lock(&pa_mutex);
#endif
        while (sys_ringbuf_GetReadAvailable(&pa_inring) <
            (long)(sys_inchannels * DEFDACBLKSIZE * sizeof(float)))
#ifdef THREADSIGNAL
                pthread_cond_wait(&pa_sem, &pa_mutex);
#else
#ifdef _WIN32
                Sleep(1);
#else
                usleep(1000);
#endif /* _WIN32 */
#endif /* THREADSIGNAL */
#ifdef THREADSIGNAL
        pthread_mutex_unlock(&pa_mutex);
#endif
    }
    pa_started = 1;

    if (sys_inchannels)
    {
        sys_ringbuf_Read(&pa_inring, conversionbuf,
            sys_inchannels*(DEFDACBLKSIZE*sizeof(float)));
        for (j = 0, fp = sys_soundin, fp2 = conversionbuf;
            j < sys_inchannels; j++, fp2++)
                for (k = 0, fp3 = fp2; k < DEFDACBLKSIZE;
                    k++, fp++, fp3 += sys_inchannels)
                        *fp = *fp3;
    }

    if ((timenow = sys_getrealtime()) - timeref > 0.002)
    {
        rtnval = SENDDACS_SLEPT;
    }
    memset(sys_soundout, 0, DEFDACBLKSIZE*sizeof(t_sample)*sys_outchannels);
    return rtnval;
}
Ejemplo n.º 5
0
int alsa_send_dacs(void)
{
    static double timenow;
    double timelast;
    t_sample *fp, *fp1, *fp2;
    int i, j, k, err, iodev, result, ch, resync = 0;;
    int chansintogo, chansouttogo;
    unsigned int transfersize;

    if (alsa_usemmap)
        return (alsamm_send_dacs());

    if (!alsa_nindev && !alsa_noutdev)
        return (SENDDACS_NO);

    chansintogo = STUFF->st_inchannels;
    chansouttogo = STUFF->st_outchannels;
    transfersize = DEFDACBLKSIZE;

    timelast = timenow;
    timenow = sys_getrealtime();

#ifdef DEBUG_ALSA_XFER
    if (timenow - timelast > 0.050)
        post("long wait between calls: %d",
            (int)(1000 * (timenow - timelast))), fflush(stderr);
    callno++;
#endif


    for (iodev = 0; iodev < alsa_nindev; iodev++)
    {
        result = snd_pcm_state(alsa_indev[iodev].a_handle);
        if (result == SND_PCM_STATE_XRUN)
        {
            int res2 = snd_pcm_start(alsa_indev[iodev].a_handle);
            fprintf(stderr, "restart alsa input\n");
            if (res2 < 0)
                fprintf(stderr, "alsa xrun recovery apparently failed\n");
        }
        snd_pcm_status(alsa_indev[iodev].a_handle, alsa_status);
        if (snd_pcm_status_get_avail(alsa_status) < transfersize)
            return (SENDDACS_NO);
    }
    for (iodev = 0; iodev < alsa_noutdev; iodev++)
    {
        result = snd_pcm_state(alsa_outdev[iodev].a_handle);
        if (result == SND_PCM_STATE_XRUN)
        {
            int res2 = snd_pcm_start(alsa_outdev[iodev].a_handle);
            fprintf(stderr, "restart alsa output\n");
            if (res2 < 0)
                fprintf(stderr, "alsa xrun recovery apparently failed\n");
        }
        snd_pcm_status(alsa_outdev[iodev].a_handle, alsa_status);
        if (snd_pcm_status_get_avail(alsa_status) < transfersize)
            return (SENDDACS_NO);
    }

#ifdef DEBUG_ALSA_XFER
    post("xfer %d", transfersize);
#endif
    /* do output */
    for (iodev = 0, fp1 = STUFF->st_soundout, ch = 0;
        iodev < alsa_noutdev; iodev++)
    {
        int thisdevchans = alsa_outdev[iodev].a_channels;
        int chans = (chansouttogo < thisdevchans ? chansouttogo : thisdevchans);
        chansouttogo -= chans;

        if (alsa_outdev[iodev].a_sampwidth == 4)
        {
            for (i = 0; i < chans; i++, ch++, fp1 += DEFDACBLKSIZE)
                for (j = i, k = DEFDACBLKSIZE, fp2 = fp1; k--;
                     j += thisdevchans, fp2++)
            {
                float s1 = *fp2 * INT32_MAX;
                ((t_alsa_sample32 *)alsa_snd_buf)[j] = CLIP32(s1);
            }
            for (; i < thisdevchans; i++, ch++)
                for (j = i, k = DEFDACBLKSIZE; k--; j += thisdevchans)
                    ((t_alsa_sample32 *)alsa_snd_buf)[j] = 0;
        }
        else if (alsa_outdev[iodev].a_sampwidth == 3)
        {
            for (i = 0; i < chans; i++, ch++, fp1 += DEFDACBLKSIZE)
                for (j = i, k = DEFDACBLKSIZE, fp2 = fp1; k--;
                     j += thisdevchans, fp2++)
            {
                int s = *fp2 * 8388352.;
                if (s > 8388351)
                    s = 8388351;
                else if (s < -8388351)
                    s = -8388351;
#if BYTE_ORDER == LITTLE_ENDIAN
                ((char *)(alsa_snd_buf))[3*j] = (s & 255);
                ((char *)(alsa_snd_buf))[3*j+1] = ((s>>8) & 255);
                ((char *)(alsa_snd_buf))[3*j+2] = ((s>>16) & 255);
#else
                fprintf(stderr, "big endian 24-bit not supported");
#endif
            }
            for (; i < thisdevchans; i++, ch++)
                for (j = i, k = DEFDACBLKSIZE; k--; j += thisdevchans)
                    ((char *)(alsa_snd_buf))[3*j] =
                    ((char *)(alsa_snd_buf))[3*j+1] =
                    ((char *)(alsa_snd_buf))[3*j+2] = 0;
        }
        else        /* 16 bit samples */
        {
            for (i = 0; i < chans; i++, ch++, fp1 += DEFDACBLKSIZE)
                for (j = ch, k = DEFDACBLKSIZE, fp2 = fp1; k--;
                     j += thisdevchans, fp2++)
            {
                int s = *fp2 * 32767.;
                if (s > 32767)
                    s = 32767;
                else if (s < -32767)
                    s = -32767;
                ((t_alsa_sample16 *)alsa_snd_buf)[j] = s;
            }
            for (; i < thisdevchans; i++, ch++)
                for (j = ch, k = DEFDACBLKSIZE; k--; j += thisdevchans)
                    ((t_alsa_sample16 *)alsa_snd_buf)[j] = 0;
        }
        result = snd_pcm_writei(alsa_outdev[iodev].a_handle, alsa_snd_buf,
            transfersize);

        if (result != (int)transfersize)
        {
    #ifdef DEBUG_ALSA_XFER
            if (result >= 0 || errno == EAGAIN)
                post("ALSA: write returned %d of %d\n",
                        result, transfersize);
            else post("ALSA: write: %s\n",
                         snd_strerror(errno));
    #endif
            sys_log_error(ERR_DATALATE);
            if (result == -EPIPE)
            {
                result = snd_pcm_prepare(alsa_indev[iodev].a_handle);
                if (result < 0)
                    fprintf(stderr, "read reset error %d\n", result);
            }
            else fprintf(stderr, "read other error %d\n", result);
            resync = 1;
        }

        /* zero out the output buffer */
        memset(STUFF->st_soundout, 0, DEFDACBLKSIZE * sizeof(*STUFF->st_soundout) *
               STUFF->st_outchannels);
        if (sys_getrealtime() - timenow > 0.002)
        {
    #ifdef DEBUG_ALSA_XFER
            post("output %d took %d msec\n",
                    callno, (int)(1000 * (timenow - timelast))), fflush(stderr);
    #endif
            timenow = sys_getrealtime();
            sys_log_error(ERR_DACSLEPT);
        }
    }
Ejemplo n.º 6
0
void sys_open_audio(int naudioindev, int *audioindev, int nchindev,
    int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev,
    int *choutdev, int rate, int advance, int enable)
{
#ifdef ROCKBOX
    int i;
#else
    int i, *ip;
#endif
    int defaultchannels = SYS_DEFAULTCH;
    int inchans, outchans;
    if (rate < 1)
    	rate = SYS_DEFAULTSRATE;
#ifdef ROCKBOX
    pd_audio_init();
#else
    audio_init();
#endif
    	/* Since the channel vector might be longer than the
	audio device vector, or vice versa, we fill the shorter one
	in to match the longer one.  Also, if both are empty, we fill in
	one device (the default) and two channels. */ 
    if (naudioindev == -1)
    { 	    	/* no input audio devices specified */
	if (nchindev == -1)
	{
	    nchindev=1;
	    chindev[0] = defaultchannels;
	    naudioindev = 1;
	    audioindev[0] = DEFAULTAUDIODEV;
	}
	else
	{
	    for (i = 0; i < MAXAUDIOINDEV; i++)
      	        audioindev[i] = i;
	    naudioindev = nchindev;
	}
    }
    else
    {
	if (nchindev == -1)
	{
	    nchindev = naudioindev;
	    for (i = 0; i < naudioindev; i++)
	    	chindev[i] = defaultchannels;
	}
	else if (nchindev > naudioindev)
	{
	    for (i = naudioindev; i < nchindev; i++)
	    {
	    	if (i == 0)
		    audioindev[0] = DEFAULTAUDIODEV;
		else audioindev[i] = audioindev[i-1] + 1;
    	    }
	    naudioindev = nchindev;
	}
	else if (nchindev < naudioindev)
	{
	    for (i = nchindev; i < naudioindev; i++)
	    {
	    	if (i == 0)
		    chindev[0] = defaultchannels;
		else chindev[i] = chindev[i-1];
    	    }
	    naudioindev = nchindev;
	}
    }

    if (naudiooutdev == -1)
    { 	    	/* not set */
	if (nchoutdev == -1)
	{
	    nchoutdev=1;
	    choutdev[0]=defaultchannels;
	    naudiooutdev=1;
	    audiooutdev[0] = DEFAULTAUDIODEV;
	}
	else
	{
	    for (i = 0; i < MAXAUDIOOUTDEV; i++)
      	        audiooutdev[i] = i;
	    naudiooutdev = nchoutdev;
	}
    }
    else
    {
	if (nchoutdev == -1)
	{
	    nchoutdev = naudiooutdev;
	    for (i = 0; i < naudiooutdev; i++)
	    	choutdev[i] = defaultchannels;
	}
	else if (nchoutdev > naudiooutdev)
	{
	    for (i = naudiooutdev; i < nchoutdev; i++)
	    {
	    	if (i == 0)
		    audiooutdev[0] = DEFAULTAUDIODEV;
		else audiooutdev[i] = audiooutdev[i-1] + 1;
    	    }
	    naudiooutdev = nchoutdev;
	}
	else if (nchoutdev < naudiooutdev)
	{
	    for (i = nchoutdev; i < naudiooutdev; i++)
	    {
	    	if (i == 0)
		    choutdev[0] = defaultchannels;
		else choutdev[i] = choutdev[i-1];
    	    }
	    naudiooutdev = nchoutdev;
	}
    }

    	/* count total number of input and output channels */
    for (i = inchans = 0; i < naudioindev; i++)
    	inchans += chindev[i];
    for (i = outchans = 0; i < naudiooutdev; i++)
    	outchans += choutdev[i];
    	/* if no input or output devices seem to have been specified,
	this really means just disable audio, which we now do.  Meanwhile,
	we can set audio input and output devices to their defaults. */
    if (!inchans && !outchans)
    {
    	enable = 0;
	naudioindev = nchindev = naudiooutdev = nchoutdev = 1;
	audioindev[0] = audiooutdev[0] = DEFAULTAUDIODEV;
	chindev[0] = choutdev[0] = 0;
    }
    sys_schedadvance = advance * 1000;
    sys_setchsr(inchans, outchans, rate);
    sys_log_error(ERR_NOTHING);

    if (enable && (inchans > 0 || outchans > 0))
    {
#ifdef USEAPI_PORTAUDIO
	if (sys_audioapi == API_PORTAUDIO)
	{
    	    int blksize = (sys_blocksize ? sys_blocksize : 64);
	    pa_open_audio(inchans, outchans, rate, sys_soundin, sys_soundout,
		blksize, sys_advance_samples/blksize,
		    (naudiooutdev > 0 ? audioindev[0] : 0),
			(naudiooutdev > 0 ? audiooutdev[0] : 0));
	}
else
#endif
#ifdef USEAPI_JACK
	if (sys_audioapi == API_JACK) 
	    jack_open_audio((naudioindev > 0 ? chindev[0] : 0),
			    (naudiooutdev > 0 ? choutdev[0] : 0), rate);

	else
#endif	  
#ifdef USEAPI_OSS
	if (sys_audioapi == API_OSS)
	    oss_open_audio(naudioindev, audioindev, nchindev, chindev,
    		    naudiooutdev, audiooutdev, nchoutdev, choutdev, rate);
	else
#endif
#ifdef USEAPI_ALSA
    	    /* for alsa, only one device is supported; it may
	    be open for both input and output. */
	if (sys_audioapi == API_ALSA)
	    alsa_open_audio(naudioindev, audioindev, nchindev, chindev,
    		    naudiooutdev, audiooutdev, nchoutdev, choutdev, rate);
	else 
#endif
#ifdef USEAPI_MMIO
	if (sys_audioapi == API_MMIO)
	    mmio_open_audio(naudioindev, audioindev, nchindev, chindev,
    		    naudiooutdev, audiooutdev, nchoutdev, choutdev, rate);
	else
#endif
#ifdef USEAPI_ROCKBOX
        if (sys_audioapi == API_ROCKBOX)
            rockbox_open_audio(rate);
        else
#endif
    	    post("unknown audio API specified");
    }
    sys_save_audio_params(naudioindev, audioindev, chindev,
    	naudiooutdev, audiooutdev, choutdev, rate, advance);
    if (sys_inchannels == 0 && sys_outchannels == 0)
    	enable = 0;
    audio_state = enable;
#ifndef ROCKBOX
    sys_vgui("set pd_whichapi %d\n",  (audio_isopen() ? sys_audioapi : 0));
#endif
    sched_set_using_dacs(enable);
}