• zero-cost abstractions for-in loops in C

    03/09/2021 at 22:59 0 comments

    This is a simple example of zero cost abstractions that might make your code easier to read.

    I really like the structure of the for loop in python. It almost sounds like a normal English sentence and is therefore more intuitive to understand.

    for item in iterable:
        do_stuff_with(item)

    I wanted a similar syntax in C. This can easily be done with two macros.

    The COUNT_OF macro is from the Chromium code base and computes the number of elements in a C array.

    The FOR_IN macro takes a data type, variable name, array reference and code to execute with the variable. It constructs a normal C for loop with these inputs.

    for(type *var = list; var < (type *)(list+COUNT_OF(list)); var++){
        //code
    }

     In the following code you can see both macros and some code using them.

    #include <stdio.h>
    
    #define COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
    
    #define FOR_IN(VAR, LIST, \
                CODE)\
            for(typeof(LIST[0]) *VAR = LIST; VAR < (typeof(LIST[0]) *)(LIST + COUNT_OF(LIST)); VAR++)\
                CODE
    
    typedef struct {
        char c;
    } foo_s_t;
    
    unsigned int ints[] = {1, 2, 3};
    
    void main(void) {
        FOR_IN(i_p, ints, {
            printf("%d\n", *i_p);
        })
    
        foo_s_t foos[] = {
            {.c = 'H'},
            {.c = 'i'}
        };
    
        FOR_IN(foo_s_p, foos, {
            printf("%c", foo_s_p->c);
        })
    }
    

     This is the resulting output.

    $ ./a.out
    1
    2
    3
    Hi 

  • Steam Link

    12/02/2018 at 18:21 0 comments

    ValveSoftware/steamlink-sdk on GitHub

    # uname -a
    Linux steamlink-5C54 3.8.13-mrvl #96 PREEMPT Wed Nov 14 13:40:59 PST 2018 armv7l GNU/Linux
    
    # cat /etc/fstab
    sys                     /sys    sysfs   defaults        0       0
    mdev            /dev    tmpfs   defaults        0       0
    proc            /proc   proc    defaults        0       0
    usb                     /proc/bus/usb   usbfs   defaults 0      0
    
    # cat /proc/cpuinfo
    processor       : 0
    model name      : ARMv7 Processor rev 0 (v7l)
    BogoMIPS        : 995.32
    Features        : swp half thumb fastmult vfp edsp thumbee neon vfpv3 tls
    CPU implementer : 0x41
    CPU architecture: 7
    CPU variant     : 0x3
    CPU part        : 0xc09
    CPU revision    : 0
    
    Hardware        : MV88DE3108
    Revision        : 0000
    Serial          : 0000000000000000
    
    # lsusb
    Bus 001 Device 002: ID 0424:2514
    Bus 001 Device 001: ID 1d6b:0002
    Bus 001 Device 003: ID 28de:1142
    Bus 001 Device 004: ID 13fe:1f23
    
    # lspci
    lspci: /sys/bus/pci/devices: No such file or directory
    
    # mount
    rootfs on / type rootfs (rw)
    /dev/mtdblock9 on / type yaffs2 (ro,relatime)
    none on /dev type tmpfs (rw,relatime)
    sys on /sys type sysfs (rw,relatime)
    proc on /proc type proc (rw,relatime)
    devtmpfs on /dev type tmpfs (rw,relatime)
    devpts on /dev/pts type devpts (rw,relatime,mode=600)
    tmpfs on /tmp type tmpfs (rw,relatime)
    tmpfs on /mnt type tmpfs (rw,relatime)
    /dev/block/mtdblock4 on /mnt/factory_setting type yaffs2 (ro,relatime)
    /dev/block/mtdblock10 on /mnt/scratch type yaffs2 (rw,relatime)
    /dev/block/mtdblock3 on /mnt/config type yaffs2 (rw,relatime)
    unionfs on /etc type unionfs (rw,relatime,dirs=/mnt/config/overlay/etc=rw:/etc=ro)
    unionfs on /var type unionfs (rw,relatime,dirs=/mnt/config/overlay/var=rw:/var=ro)
    unionfs on /home/steam type unionfs (rw,relatime,dirs=/mnt/config/overlay/home/steam=rw:/home/steam=ro)
    unionfs on /usr/local type unionfs (rw,relatime,dirs=/mnt/config/overlay/usr/local=rw:/usr/local=ro)
    tmpfs on /var/run type tmpfs (rw,relatime)
    /dev/loop0 on /home/apps type ext4 (rw,relatime,data=ordered)
    

  • Using a Program as audio source under Linux with Pulseaudio

    04/26/2018 at 05:56 0 comments

    Suppose you want to record the audio of just one program or want to redirect it into another program (e.g. GNU Radio) and don't want to use weird third party software that does everything in a black box. That is easily done with a pulseaudio module-combine.

    Prerequisites

    The tools I will be using here are pactl, pacat and pavucontrol. Under Arch Linux you need to install the packages libpulse pavucontrol.

    Steps

    1.  load the module-combine into the running sound server and give it a nice name.
      1. pactl load-module module-combine sink_name=combine
    2. Open pavucontrol and set the output of the program which's audio you want to the "Simultaneous output" and the output of the "Simultaneous output" to you default output.
    3. Use pacat or parec to get the samples out of stdout.
      1. pacat -r -d combine.monitor

    Application

    In my case i wanted to be able to access the samples via a local UDP connection to use it with the GNU Radio UDP source.

    pacat -r -d combine.monitor | while true; do nc -u localhost 1337; done

    The while loop makes it so that I can stop and start the listening side without having to restart this sending line of code.

    Because this is stereo audio, the samples come in as 2-tuples (aka. vectors) so i need to convert them into to streams and add the streams.

    I seemed to have glitches with a Payload Size of 1472 so I changed it to 2**18

    Tipps

    The audio samples you get are signed 16 bit LE stereo pairs. Sometimes you need mono. You can do the conversion with sox.

    pacat -r -d combine.monitor | sox -r 44100 -t raw -e signed-integer -L -b 16 -c 2 - -c 1 -e signed-integer -b 16 -t raw -

    The long flag version for better understanding is

    pacat -r -d combine.monitor | sox --rate 44100 \
    --type raw \
    --encoding signed-integer \
    --endian little \
    --bits 16 \
    --channels 2 \
    - \
    --channels 1 \
    --encoding signed-integer \
    --bits 16 \
    --type raw \
    -