This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

DM365 Audio capture -- Rate problem

My audio capture is misbehaving.  Normally, when my app reads 16bit pcm at 48000khz the data arrives normally, but about once every couple minutes I get a huge chunk of data.  It looks like a buffering problem.

Our codec supports 24bit capture in a 32bit I2s window ( 32bits left, 32 bits right).  I've modified the sound/soc/davinci/davinci-* drivers so that the hardware aways captures 32 bits and I'm using ALSA to truncate the the data to 16bit PCM.

 

here is  a normal run:

~ # audcap -z 8192 -d 2
 -- force capture size to  8192/0x2000
 -- duration  set to 2.000000
Audcap:         rate=48000, samp_size=2, num_channels=2
        buffer is 0x4/4 bytes
Starting Capture using buffer_sz=8192:
 0.00: 125235.05 bps (31308.76 samp/s): 8192 in 0.065s (er= 53.31%)!! max@00011c=07f3
 0.04: 192052.51 bps (48013.13 samp/s): 8192 in 0.043s (er= -0.03%)   max@0000e2=07f2
 0.09: 192079.53 bps (48019.88 samp/s): 8192 in 0.043s (er= -0.04%)   max@00008a=07f2
 0.13: 192097.55 bps (48024.39 samp/s): 8192 in 0.043s (er= -0.05%)   max@00001c=07f2
 0.17: 192048.01 bps (48012.00 samp/s): 8192 in 0.043s (er= -0.03%)   max@0000fa=07f2
 0.21: 191850.12 bps (47962.53 samp/s): 8192 in 0.043s (er=  0.08%)   max@000b74=07f3
 0.26: 192793.77 bps (48198.44 samp/s): 8192 in 0.042s (er= -0.41%)   max@0000fe=07f2
 0.30: 192066.02 bps (48016.51 samp/s): 8192 in 0.043s (er= -0.03%)   max@000446=07f3
 0.34: 192147.11 bps (48036.78 samp/s): 8192 in 0.043s (er= -0.08%)   max@0008c0=07f3
 0.38: 192698.53 bps (48174.63 samp/s): 8192 in 0.043s (er= -0.36%)   max@000e66=07f3
 0.43: 191967.01 bps (47991.75 samp/s): 8192 in 0.043s (er=  0.02%)   max@000fdc=07f3
 0.47: 192151.62 bps (48037.90 samp/s): 8192 in 0.043s (er= -0.08%)   max@000288=07f3
 0.51: 192079.53 bps (48019.88 samp/s): 8192 in 0.043s (er= -0.04%)   max@000288=07f3
 0.55: 191679.54 bps (47919.88 samp/s): 8192 in 0.043s (er=  0.17%)   max@000268=07f3
 0.60: 192472.16 bps (48118.04 samp/s): 8192 in 0.043s (er= -0.25%)   max@000230=07f3
 0.64: 192075.03 bps (48018.76 samp/s): 8192 in 0.043s (er= -0.04%)   max@0001e0=07f3
 0.68: 192016.50 bps (48004.13 samp/s): 8192 in 0.043s (er= -0.01%)   max@00017a=07f3
 0.73: 191922.03 bps (47980.51 samp/s): 8192 in 0.043s (er=  0.04%)   max@0000fa=07f3
 0.77: 192223.76 bps (48055.94 samp/s): 8192 in 0.043s (er= -0.12%)   max@000058=07f3
 0.81: 192106.56 bps (48026.64 samp/s): 8192 in 0.043s (er= -0.06%)   max@000228=07f3
 0.85: 191782.75 bps (47945.69 samp/s): 8192 in 0.043s (er=  0.11%)   max@0003da=07f3
 0.90: 192327.56 bps (48081.89 samp/s): 8192 in 0.043s (er= -0.17%)   max@00006a=07f3
 0.94: 192057.02 bps (48014.25 samp/s): 8192 in 0.043s (er= -0.03%)   max@0001e8=07f3
 0.98: 192075.03 bps (48018.76 samp/s): 8192 in 0.043s (er= -0.04%)   max@0000c8=07f3
 1.02: 191967.01 bps (47991.75 samp/s): 8192 in 0.043s (er=  0.02%)   max@000206=07f3
 1.07: 192178.67 bps (48044.67 samp/s): 8192 in 0.043s (er= -0.09%)   max@0000b6=07f3
 1.11: 192102.05 bps (48025.51 samp/s): 8192 in 0.043s (er= -0.05%)   max@000084=07f3
 1.15: 192039.01 bps (48009.75 samp/s): 8192 in 0.043s (er= -0.02%)   max@00016c=07f3
 1.19: 191719.91 bps (47929.98 samp/s): 8192 in 0.043s (er=  0.15%)   max@00010a=07f3
 1.24: 192192.19 bps (48048.05 samp/s): 8192 in 0.043s (er= -0.10%)   max@0002f2=07f3
 1.28: 192061.52 bps (48015.38 samp/s): 8192 in 0.043s (er= -0.03%)   max@000250=07f3
 1.32: 192277.90 bps (48069.48 samp/s): 8192 in 0.043s (er= -0.14%)   max@00006e=07f3
 1.37: 192021.00 bps (48005.25 samp/s): 8192 in 0.043s (er= -0.01%)   max@0000d0=07f3
 1.41: 192052.51 bps (48013.13 samp/s): 8192 in 0.043s (er= -0.03%)   max@000114=07f3
 1.45: 192147.11 bps (48036.78 samp/s): 8192 in 0.043s (er= -0.08%)   max@000140=07f3
 1.49: 192057.02 bps (48014.25 samp/s): 8192 in 0.043s (er= -0.03%)   max@00014a=07f3
 1.54: 192052.51 bps (48013.13 samp/s): 8192 in 0.043s (er= -0.03%)   max@00001a=07f3
 1.58: 192106.56 bps (48026.64 samp/s): 8192 in 0.043s (er= -0.06%)   max@000114=07f3
 1.62: 192079.53 bps (48019.88 samp/s): 8192 in 0.043s (er= -0.04%)   max@0000d2=07f3
 1.66: 192088.54 bps (48022.14 samp/s): 8192 in 0.043s (er= -0.05%)   max@000076=07f3
 1.71: 192057.02 bps (48014.25 samp/s): 8192 in 0.043s (er= -0.03%)   max@000002=07f3
 1.75: 192030.00 bps (48007.50 samp/s): 8192 in 0.043s (er= -0.02%)   max@0001a4=07f3
 1.79: 191827.65 bps (47956.91 samp/s): 8192 in 0.043s (er=  0.09%)   max@0000f6=07f3
 1.83: 191935.52 bps (47983.88 samp/s): 8192 in 0.043s (er=  0.03%)   max@000f5e=07f4
 1.88: 192472.16 bps (48118.04 samp/s): 8192 in 0.043s (er= -0.25%)   max@000184=07f3
 1.92: 191841.13 bps (47960.28 samp/s): 8192 in 0.043s (er=  0.08%)   max@000090=07f3
 1.96: 192268.88 bps (48067.22 samp/s): 8192 in 0.043s (er= -0.14%)   max@000800=07f4
... total capture time is    2.02883, total error =   1.442 %
~ #

I am reading 8k buffers and the data comes in at a very regular rate

Here is an example of a the rate issue:

20.74: 191917.54 bps (47979.38 samp/s): 8192 in 0.043s (er=  0.04%)   max@00008e=07f2
20.78: 192052.51 bps (48013.13 samp/s): 8192 in 0.043s (er= -0.03%)   max@000092=07f2
20.82: 192088.54 bps (48022.14 samp/s): 8192 in 0.043s (er= -0.05%)   max@000082=07f2
20.86: 192228.27 bps (48057.07 samp/s): 8192 in 0.043s (er= -0.12%)   max@000058=07f2
20.91: 191877.08 bps (47969.27 samp/s): 8192 in 0.043s (er=  0.06%)   max@0004c8=07f3
20.95: 192102.05 bps (48025.51 samp/s): 8192 in 0.043s (er= -0.05%)   max@00014c=07f3
20.99: 192093.05 bps (48023.26 samp/s): 8192 in 0.043s (er= -0.05%)   max@0000d2=07f3
21.03: 251798.12 bps (62949.53 samp/s): 8192 in 0.033s (er=-23.75%)!! max@00003a=07f3

21.08: 192214.74 bps (48053.68 samp/s): 8192 in 0.043s (er= -0.11%)   max@000ece=07f3
21.12: 192003.00 bps (48000.75 samp/s): 8192 in 0.043s (er= -0.00%)   max@0001d4=07f3
21.16: 191832.15 bps (47958.04 samp/s): 8192 in 0.043s (er=  0.09%)   max@0000f4=07f2
21.21: 192354.65 bps (48088.66 samp/s): 8192 in 0.043s (er= -0.18%)   max@0002f8=07f3
21.25: 192057.02 bps (48014.25 samp/s): 8192 in 0.043s (er= -0.03%)   max@000066=07f2
21.29: 192079.53 bps (48019.88 samp/s): 8192 in 0.043s (er= -0.04%)   max@000c88=07f3

for this 8k capture it looks like I'm getting the full block in 33ms -- or about 63Khz instead of 48Khz.

Had anybody seen this issue or know of a fix?

I am using 'Linux 10.8.104.71 2.6.32-rc2-davinci1' ( PSP37) kernel.

Brett

 

  • Capture example program.

     

    ~ # cat src/audcap.c
    /**
     * @file audcap.c
     * @brief Program to illustrate /dev/dsp device
     */

    #include <stdio.h>
    #include <stdint.h>
    #include <stdlib.h>
    #include <string.h>
    #include <fcntl.h>
    #include <errno.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/ioctl.h>
    #include <stdlib.h>
    #include <linux/soundcard.h>
    #include <unistd.h>
    #include <sys/time.h>


    int   rate = 48000;              // base sampling rate 48Khz
    int   samp_size = 16;            // 2 bytes per sample
    int   verbose   = 0;             // verbose level - default is no debug
    int   channels  = 2;             // stereo - 2 channels per sample
    char  fname[80] = "/dev/null";   // do not store result

    double buf_dur   = 0.5;         // default -- read data in 500ms chunks
    double dur       = 10.0;        // default -- record 10 seconds
    int    force_sz  = 0;           // force input buffersize

    /*
     * @brief number of seconds since last timer reset
     */
    static double base_tm =  0.0;

    /* @brief get number of seconds since timer reset
     *
     */
    double get_time()
    {
            // faster method?
            struct timeval   tv;
            double tm;
            gettimeofday( &tv, NULL);
            tm =  (1.0*tv.tv_usec) / 1000.0 / 1000.0;   // microseconds
            tm += (double) tv.tv_sec;                   // full seconds
            return tm - base_tm;
    }


    /*
     * @brief reset time origin
     */
    void  init_time()
    {
            base_tm = get_time();
    }

    void hexdump( void *ptr, int len, char *banner, int arg)
    {
            int ofs;
            unsigned char *byte_ptr = (unsigned char *) ptr;

            printf("%s(%d) %d bytes @ 0x%p\n",
                   banner, arg, len, ptr);
            for (ofs = 0; ofs < len ; ofs +=16) {
                    printf("%08x: ", ofs);
                    printf("%02x %02x %02x %02x %02x %02x %02x %02x . ",
                           byte_ptr[0], byte_ptr[1], byte_ptr[2], byte_ptr[3],
                           byte_ptr[4], byte_ptr[5], byte_ptr[6], byte_ptr[7]);
                    byte_ptr += 8;
                    printf("%02x %02x %02x %02x %02x %02x %02x %02x\n",
                           byte_ptr[0], byte_ptr[1], byte_ptr[2], byte_ptr[3],
                           byte_ptr[4], byte_ptr[5], byte_ptr[6], byte_ptr[7]);
                    byte_ptr += 8;
            }
    }




    void args( int argc, char *argv[])
    {
            //int flags;
            int opt;

            // getopt
            while (( opt = getopt( argc, argv,"z:g:d:c:v:r:o:")) != -1) {
                    switch (opt) {
                    case 'z':
                        force_sz = atoi(optarg);
                        printf(" -- force capture size to  %d/0x%x\n",
                               force_sz, force_sz);
                        break;
                    case 'g':
                            buf_dur =  1.0 *atoi(optarg)/1000.0;
                            printf(" -- cap_seg  set to %dms\n",
                                   (int) (buf_dur/1000));
                            break;
                    case 'd':
                            dur =  1.0 *atoi(optarg);
                            printf(" -- duration  set to %f\n", dur);
                            break;
                    case 'c':
                            channels = atoi(optarg);
                            printf(" -- channels set to %d\n", channels);
                            break;
                    case 'v':
                            verbose = atoi(optarg);
                            printf(" -- verbose set to %d\n", verbose);
                            break;
                    case 'r':
                            rate = atoi(optarg);
                            printf(" -- rate set to %d\n", rate);
                            break;
                    case 'o':
                            strcpy(fname, optarg);
                            printf(" -- output file is '%s'\n", fname);
                            break;
                    default:
                            fprintf(stderr,
                                    "Usage: %s "
                                    " -d <duration_in_s>"
                                    " -c <channels>"
                                    " -v <verbose>"
                                    " -r <rate>"
                                    " -o <output_fname>"
                                    " -g <segment_size_in_ms> \n"
                                    " -z <force read buffer size in bytes> \n",
                                    argv[0]);
                            exit( -1);
                    }
            }
    }



    int main( int argc, char *argv[])
    {
            int f_in;       /* sound device file descriptor */
            FILE *fd_out;   /* file output  */
            int arg;        /* argument for ioctl calls */
            int status;     /* return status of system calls */
            int nbytes;     /* number of bytes read */
            double t0, tdiff;

            /* this buffer holds the digitized audio */
            unsigned char *buf;
            int            buf_sz;

            args(argc, argv);

            printf("Audcap:  "
                   "\trate=%d, samp_size=%d, num_channels=%d\n"
                   "\tbuffer is 0x%x/%d bytes\n",
                   rate, channels, channels,
                   sizeof buf, sizeof buf);

            init_time();

            if (verbose > 0) {
                    t0 = get_time(); sleep(2); tdiff = get_time() - t0;
                    printf("!! timecheck: 2sec = %f\n", tdiff);
            }

            buf_sz = (int) (buf_dur * rate * channels * samp_size /8);
            if ( force_sz) {
                buf_sz = force_sz;
                buf_dur = 8.0*buf_sz / rate / channels / samp_size;
            }

            buf = malloc(buf_sz);
            if ( buf == NULL) {
                    perror("Memory Error");
                    return -1;
            }

            /* open sound device */
            f_in = open("/dev/dsp", O_RDWR);
            if (f_in < 0) {
                    perror("open of /dev/dsp failed\n");
                    exit(1);
            }

            /* open sound device */
            fd_out = fopen (fname, "rw+" );
            if (fd_out < 0) {
                printf("create of '%s' failed\n", fname);
                perror("create failed\n");
                    exit(1);
            }

            char raw_buf[32768];
            setvbuf( fd_out, raw_buf, _IOFBF, sizeof raw_buf);

            // set sampling parms:
            //        -- 2 bytes per sample
            //        -- num channels
            //        -- sampling rate

            // need to make this an argument!!!
            arg = AFMT_S16_LE;
            status = ioctl(f_in, SNDCTL_DSP_SETFMT, &arg);
            if (status == -1)
                    perror("SOUND_SNDCTRL_DSP_SETFMT ioctl failed");
            if (arg != AFMT_S16_LE)
                    perror("audcap: unable to set fmt\n");

            arg = channels;  /* mono or stereo */
            status = ioctl(f_in, SNDCTL_DSP_CHANNELS, &arg);
            if (status == -1)
                    perror("SOUND_SNDCTRL_DSP_CHANNELS ioctl failed");
            if (arg != channels)
                    printf("audcap:unable to set number of channels\n");

            arg = rate;        /* sampling rate */
            status = ioctl(f_in, SNDCTL_DSP_SPEED, &arg);
            if (status == -1)
                    perror("SOUND_SNDCTRL_DSP_SPEED ioctl failed");
            if (arg != rate)
                    printf("audcap:unable to set rate (%d,%d)\n",
                           arg,rate);

            printf("Starting Capture using buffer_sz=%d:\n", buf_sz);

            double secs = 0;
            double tstart = get_time();
            double err;
            t0 = get_time();
            while (secs <  dur) {
                    nbytes = read(f_in, buf, buf_sz); /* capture some sound */
                    tdiff = get_time() - t0;
                    t0 = get_time();
                    if (nbytes != buf_sz) {
                            //perror("read wrong number of bytes");
                            printf("read asks for %d bytes, but gets %d bytes\n",
                                   buf_sz, nbytes);
                    }
                    fwrite(buf, nbytes, 1, fd_out);  /* save it */
                    printf("%5.2f:",secs);
                    err =  100.0 * (tdiff/buf_dur) - 100.0;
                    printf("%10.2f bps (%8.2f samp/s): "
                           "%d in %5.3fs (er=%6.2f%%)%s",
                           (1.0*nbytes/tdiff),
                           (8.0*nbytes/samp_size/channels)/tdiff,
                           nbytes, tdiff,
                           err, (abs((int) err) > 2)? "!!" : "  ");


                    if (verbose > 2) {
                            hexdump( buf, 2*16, "Audio @", secs);
                    }
                    if (1) {
                        int      j;
                        int      max_index = 0;
                        int      min_index = 0;
                        int16_t  max = 0;
                        int16_t  min = 16384;
                        int16_t *aud_buf = ( int16_t *) buf;
                        for ( j = 0; j < nbytes/2; j++) {
                            if ( abs(aud_buf[j]) > max) {
                                max_index = j;
                                max = abs(aud_buf[j]);
                            }
                            if ( abs(aud_buf[j]) < min) {
                                min_index = j;
                                min = abs(aud_buf[j]);
                            }
                        }
                        printf(" max@%06x=%04x\n",
                               (int)max_index, (int)max);
                    }
                    secs += buf_dur;
            }
            double total_tdiff = get_time() - tstart;


            printf("... total capture time is %10.5f, total error = %7.3f %%\n",
                   total_tdiff, ( 100* (total_tdiff - dur)/dur));

            fclose(fd_out);
            close(f_in);

            return 0;
    }

    ~ #