Hello,

I have an amd64 laptop with OpenBSD 6.7 and I am only getting
zero-valued samples when recording. Is there any checklist I can
go through to ensure nothing is muted and that I am reading from
the correct input device?

I have tried both aucat and a C program I wrote (attached).

Thanks,
Aaron Miller
#include <stdio.h>
#include <sndio.h>
#include <stdlib.h>
#include <errno.h>

#define BUF_SAMPLES 4800
#define OUTFILE "recorded.pcm"
#define ITERATIONS 500

// ffmpeg -y -f s16le -ar 48000 -ac 1 -i recorded.pcm recorded.mp3 && mpv recorded.mp3

void print_par(struct sio_par *par);

int main(int argc, char* argv[]) {
    short *sample_buf = NULL;
    struct sio_hdl *h;
    int fail = 0;
    int started = 0;
    size_t total_bytes_read = 0;
    int i;
    size_t bytes_read;
    FILE *out = NULL;
    h = sio_open(SIO_DEVANY, SIO_REC, 0);
    if (h == NULL) {
        fprintf(stderr, "%s: we're fucked man\n", argv[0]);
        fail = 1; goto done;
    }

    struct sio_par par;
    sio_initpar(&par);

    par.bits = 8*sizeof(short);
    //par.bps = sizeof(short);
    par.sig = 1;
    par.le = 1;
    par.rchan = 1;
    par.pchan = 2; // unused
    par.rate = 48000;
    par.xrun = SIO_IGNORE;

    //print_par(&par);
    printf("running sio_setpar...\n");
    if (sio_setpar(h, &par) == 0) {
        fprintf(stderr, "%s: sio_setpar failed\n", argv[0]);
        fail = 1; goto done;
    };
    //print_par(&par);

    printf("running sio_getpar...\n");
    if (sio_getpar(h, &par) == 0) {
        fprintf(stderr, "%s: sio_getpar failed\n", argv[0]);
        fail = 1; goto done;
    };
    print_par(&par);

    if (BUF_SAMPLES % par.round != 0) {
        fprintf(stderr, "%s: samples in buf (%d) not mult of round (%d)\n", argv[0], BUF_SAMPLES, par.round);
        fail = 1; goto done;
    }

    if ((sample_buf = malloc(BUF_SAMPLES * sizeof(short))) == NULL) {
        fprintf(stderr, "%s: oh we are sooo fucked. GAME OVER MAN\n", argv[0]);
        fail = 1; goto done;
    }

    if ((out = fopen(OUTFILE, "wb")) == NULL) {
        fprintf(stderr, "%s: failed to open %s for writing\n", argv[0], OUTFILE);
        fail = 1; goto done;
    }

    if (sio_start(h) == 0) {
        fprintf(stderr, "%s: failed to sio_start\n", argv[0]);
        fail = 1; goto done;
    }
    started = 1;
    int retries = 0;
    printf("START\n");
    for (i = 0; i < ITERATIONS; i++) {
        if ((bytes_read = sio_read(h, sample_buf, BUF_SAMPLES * sizeof(short))) == 0) {
            fprintf(stderr, "%s: failed to sio_read\n", argv[0]);
            fail = 1; goto done;
        }
        total_bytes_read += bytes_read;

        size_t bytes_written;
        size_t bw;
        char* buf_ptr = (char *) sample_buf;
        for (bytes_written = 0; bytes_written < bytes_read; bytes_written += bw) {
            size_t bytes_left = bytes_read - bytes_written;
            bw = fwrite(buf_ptr, 1, bytes_left, out);
            if (bw < bytes_left && errno != EAGAIN) {
                fprintf(stderr, "%s: failed to write to file\n", argv[0]);
                perror(argv[0]);
                fail = 1; goto done;
            }
            buf_ptr += bw;
        }
    }
    printf("TOTAL BYTES READ: %d\n", total_bytes_read);

    // cleanup
done:
    if (started) {
        sio_stop(h);
    }
    if (out != NULL) {
        fclose(out);
    }
    if (sample_buf != NULL) {
        free(sample_buf);
    }
    if (h != NULL) {
        sio_close(h);
    }
    return fail;
}

void print_par(struct sio_par *par) {
    char *xrun;
    switch (par->xrun) {
        default:
            xrun = "<unknown xrun val>";
            break;
        case 0:
            xrun = "SIO_IGNORE";
            break;
        case 1:
            xrun = "SIO_SYNC";
            break;
        case 2:
            xrun = "SIO_ERROR";
            break;
    }
    printf("&sio_par{\n"
            "  bits: %d,\n"
            "  bps: %d,\n"
            "  sig: %d,\n"
            "  le: %d,\n"
            "  msb: %d,\n"
            "  rchan: %d,\n"
            "  pchan: %d,\n"
            "  rate: %d,\n"
            "  appbufsz: %d,\n"
            "  bufsz: %d,\n"
            "  round: %d,\n"
            "  xrun: %s (%d),\n"
            "}\n",
            par->bits,      /* bits per sample */
            par->bps,       /* bytes per sample */
            par->sig,       /* 1 = signed, 0 = unsigned int */
            par->le,        /* 1 = LE, 0 = BE byte order */
            par->msb,       /* 1 = MSB, 0 = LSB aligned */
            par->rchan,     /* number channels for recording */
            par->pchan,     /* number channels for playback */
            par->rate,      /* frames per second */
            par->appbufsz,  /* minimum buffer size without xruns */
            par->bufsz,     /* end-to-end buffer size (read-only) */
            par->round,     /* optimal buffer size divisor */
                 xrun,      /* what to do on overrun/underrun */
            par->xrun
        );
}

Reply via email to