[alsa-devel] Clicking issues with the output of an Onyx Blackbird

Takashi Sakamoto o-takashi at sakamocchi.jp
Sat Oct 15 20:58:24 CEST 2016


Hi,

On Oct 13 2016 22:51, Jordi Torres wrote:
> I tested all DICE outputs but as this DAW uses a non-numeric
> terminology, it have been a little complicated to check all outputs
>
> This is a reference of how ouputs are routed to connectors:
>
> Front outputs:
>
> Phone 1 & Switch in MON position -> InS0:01 + InS0:02
> Phone 1 & Switch in PH1 position -> InS0:05 + InS0:06
> Phone 2 & Switch in MON position -> InS0:01 + InS0:02
> Phone 2 & Switch in PH2 position -> InS0:07 + InS0:08
>
> Back outputs:
>
> ALT out L-> InS0:03
> ALT out R-> InS0:04
> MAIN out L -> InS0:01
> MAIN out R -> InS0:02
> MON out L -> InS0:01
> MON out R -> InS0:02
>
> I tested ADAT looped (from output ADAT to input ADAT) and clicks too
> I tested if clicks when DICE routes one input to one output and it
> doesn't click.
> I didn't test Inserts but I supouse that use InS0:01 & InS0:02

In most models with Dice II/Jr/Mini, digital interface (SPDIF/TOSLINK
and ADAT) in/out is just bypass to/from corresponding data channels in
IEEE 1394 isochronous packets. No multiplexing with the other data
channels. Furthermore, The data channels corresponding to digital
interfaces is in rear position inner a packet.

For these natures, I use the loopbacked digital interface in/out to
investigate this driver issue. The program in last of this message is a
part of my test programs for this issue.

According to the logs you sent, ALSA Dice driver adds one PCM device for
capture and _two_ PCM devices for playback to your units. So you need to
modify the program for your unit.

I think that capture 'pcm.hw:1,0,0' and playback 'pcm.hw:1,1,0' include
ADAT channels. It's better to show us the output from
'/proc/asound/card1/dice' so that we can get to know channel formations
of your unit.

In my case:
$ gcc -o test test.c -l pthread -l asound
$ ./test pcm,hw:1,0,0 48000

-------- 8< --------

#include <stdint.h>
#include <stdbool.h>
#include <unistd.h>

#include <pthread.h>

#include <alsa/asoundlib.h>

static const char *node;
static unsigned int rate;

static int set_params(snd_pcm_t *handle, int rate, snd_pcm_format_t format,
                      unsigned int *ch)
{
    snd_pcm_hw_params_t *params;
    int err;

    snd_pcm_hw_params_alloca(&params);

    err = snd_pcm_hw_params_any(handle, params);
    if (err < 0) {
        printf("snd_pcm_hw_params_any()\n");
        return err;
    }

    err = snd_pcm_hw_params_set_access(handle, params,
                       SND_PCM_ACCESS_RW_INTERLEAVED);
    if (err < 0) {
        printf("snd_pcm_hw_params_set_access()\n");
        return err;
    }

    err = snd_pcm_hw_params_set_rate(handle, params, rate, 0);
    if (err < 0) {
        printf("snd_pcm_hw_params_set_rate()\n");
        return err;
    }

    err = snd_pcm_hw_params_set_format(handle, params, format);
    if (err < 0) {
        printf("snd_pcm_hw_params_set_format()\n");
        return err;
    }

    err = snd_pcm_hw_params(handle, params);
    if (err < 0) {
        printf("snd_pcm_hw_params()\n");
        return err;
    }

    err = snd_pcm_hw_params_get_channels(params, ch);
    if (err < 0)
        printf("snd_pcm_hw_params_get_channels()\n");

    return err;
}

static int receive_pcm_s32(snd_pcm_t *handle, snd_pcm_format_t format,
                           unsigned int chs)
{
    uint32_t *buf, curr[2], expected[2];
    snd_pcm_sframes_t frames;
    unsigned int i;
    unsigned int count;
    unsigned int phase, drops;
    int err = 0;

    buf = malloc(sizeof(uint32_t) * chs * 0xff);
    if (buf == NULL)
        return -ENOMEM;

    count = 0;
    while (1) {
        frames = snd_pcm_readi(handle, buf, 0xff);
        if (frames < 0) {
            printf("snd_pcm_readi(): %s\n", snd_strerror(frames));
            err = snd_pcm_recover(handle, frames, 0);
            if (err < 0) {
                printf("snd_pcm_recover(): %s\n", snd_strerror(err));
                err = frames;
                break;
            }
            continue;
        }

        for (i = 0; i < frames; i++) {
            curr[0] = buf[chs * i + chs - 2];
            curr[1] = buf[chs * i + chs - 1];

            /* Unexpected PCM samples are in this PCM frame. */
            if (curr[0] != expected[0] || curr[1] != expected[1]) {
                if (count - phase > 10000) {
                    printf("%08d %08d: %08x %08x %08x %08x\n",
                           count - phase, drops,
                           curr[0], curr[1],
                           expected[0], expected[1]);
                    phase = count;
                    drops = 0;
                } else {
                    drops += 1;
                }
            }

            expected[0] = curr[0] + 0x100;
            if (expected[0] > 0xffff0000)
                expected[0] = 0;
            expected[1] = curr[1] + 0x100;
            if (expected[1] > 0xffff0000)
                expected[1] = 0;
            count += 1;
        }
    }

    free(buf);
    return err;
}

static void *receive_samples(void *arg)
{
    snd_pcm_t *handle = NULL;
    unsigned int chs;
    int err;

    err = snd_pcm_open(&handle, node, SND_PCM_STREAM_CAPTURE, 0);
    if (err < 0) {
        printf("snd_pcm_open(): %s\n", snd_strerror(err));
        goto end;
    }

    err = set_params(handle, rate, SND_PCM_FORMAT_S32, &chs);
    if (err < 0)
        goto end;

    err = receive_pcm_s32(handle, SND_PCM_FORMAT_S32, chs);
    if (err < 0)
        goto end;

    err = snd_pcm_hw_free(handle);
    if (err < 0)
        printf("snd_pcm_hw_free(): %s\n", snd_strerror(err));
end:
    if (handle != NULL)
        snd_pcm_close(handle);

    pthread_exit(NULL);
}

static int transfer_pcm_s32(snd_pcm_t *handle, snd_pcm_format_t format,
                            unsigned int chs)
{
    unsigned int most;
    unsigned int medium;
    unsigned int least;
    unsigned int ch;
    uint32_t *buf, sample;
    snd_pcm_sframes_t frames;
    int err = 0;

    buf = malloc(sizeof(uint32_t) * 0xff * chs);
    if (buf == NULL)
        return -ENOMEM;

    sample = 0;
    for (most = 0x00; most < 0xff; most++) {
        for (medium = 0x00; medium < 0xff; medium++) {
            /* Generate PCM frames for this iteration. */
            for (least = 0; least < 0xff; least++)  {
                sample += 1;
                if (sample > 0x00ffffff)
                    sample = 0;
                for (ch = 0; ch < chs; ch++)
                    buf[least * chs + ch] = sample << 8;
            }

            frames = snd_pcm_writei(handle, buf, 0xff);
            if (frames < 0) {
                printf("snd_pcm_writei(): %s\n", snd_strerror(frames));
                err = snd_pcm_recover(handle, frames, 0);
                if (err < 0) {
                    printf("snd_pcm_recover(): %s\n", snd_strerror(err));
                    err = frames;
                    break;
                }
                continue;
            }
        }
    }


    free(buf);
    return err;
}

int main(int argc, const char *argv[])
{
    snd_pcm_t *handle = NULL;
    unsigned int chs;
    pthread_t thread;
    int err;

    if (argc != 3) {
        printf("Two arguments are required.\n");
        printf("    PCM node in ALSA runtime configuration.\n");
        printf("    sampling rate.\n");
        return EXIT_FAILURE;
    }

    node = argv[1];
    rate = strtol(argv[2], NULL, 10);

    err = snd_pcm_open(&handle, node, SND_PCM_STREAM_PLAYBACK, 0);
    if (err < 0) {
        printf("snd_pcm_open(): %s", snd_strerror(err));
        goto end;
    }

    err = set_params(handle, rate, SND_PCM_FORMAT_S32, &chs);
    if (err < 0)
        goto end;

    err = pthread_create(&thread, NULL, receive_samples, NULL);
    if (err != 0)
        goto end;

    err = transfer_pcm_s32(handle, SND_PCM_FORMAT_S32, chs);
    if (err < 0)
        goto end;

    err = snd_pcm_drain(handle);
    if (err < 0) {
        printf("snd_pcm_drain(): %s", snd_strerror(err));
        goto end;
    }

    err = snd_pcm_hw_free(handle);
    if (err < 0)
        printf("snd_pcm_hw_free(): %s", snd_strerror(err));
end:
    if (handle != NULL)
        snd_pcm_close(handle);
    exit(EXIT_SUCCESS);
}


Regards

Takashi Sakamoto


More information about the Alsa-devel mailing list