我目前可以使用raspberry pi 3USB Audio input重定向到icecast stream。目前,当我在Raspbian Jessie Lite上pipe arecord from USB audio hw input to avconv(等效于ffmpeg)时,在小型测试中工作正常。

当您使用详细设置时,Arecord具有用于音频电平的内置文本音量计。

我认为代码位于附加的函数中。我想知道是否可以重写此函数以输出到Raspberry Pi 3 RGB LED-使用该函数的峰值变量以某种方式基于音量发送红色/黄色/绿色?

我已经包括了整个功能-和打印功能。如果可以的话,我认为代码可能可以替换print_vu_meter(perc, maxperc);

是否可以修改记录以使Raspi 3处理管道中的处理?有没有办法使用另一个线程?

在这里脱离我的联盟-只是寻找一个开始,或者是一些想法可以使想法摆脱我的头脑,或者说这是可能的。


  峰值处理程序


static void compute_max_peak(u_char *data, size_t count)
{
    signed int val, max, perc[2], max_peak[2];
    static  int run = 0;
    size_t ocount = count;
    int format_little_endian = snd_pcm_format_little_endian(hwparams.format);
    int ichans, c;

    if (vumeter == VUMETER_STEREO)
        ichans = 2;
    else
        ichans = 1;

    memset(max_peak, 0, sizeof(max_peak));
    switch (bits_per_sample) {
    case 8: {
        signed char *valp = (signed char *)data;
        signed char mask = snd_pcm_format_silence(hwparams.format);
        c = 0;
        while (count-- > 0) {
            val = *valp++ ^ mask;
            val = abs(val);
            if (max_peak[c] < val)
                max_peak[c] = val;
            if (vumeter == VUMETER_STEREO)
                c = !c;
        }
        break;
    }
    case 16: {
        signed short *valp = (signed short *)data;
        signed short mask = snd_pcm_format_silence_16(hwparams.format);
        signed short sval;

        count /= 2;
        c = 0;
        while (count-- > 0) {
            if (format_little_endian)
                sval = __le16_to_cpu(*valp);
            else
                sval = __be16_to_cpu(*valp);
            sval = abs(sval) ^ mask;
            if (max_peak[c] < sval)
                max_peak[c] = sval;
            valp++;
            if (vumeter == VUMETER_STEREO)
                c = !c;
        }
        break;
    }
    case 24: {
        unsigned char *valp = data;
        signed int mask = snd_pcm_format_silence_32(hwparams.format);

        count /= 3;
        c = 0;
        while (count-- > 0) {
            if (format_little_endian) {
                val = valp[0] | (valp[1]<<8) | (valp[2]<<16);
            } else {
                val = (valp[0]<<16) | (valp[1]<<8) | valp[2];
            }
            /* Correct signed bit in 32-bit value */
            if (val & (1<<(bits_per_sample-1))) {
                val |= 0xff<<24;    /* Negate upper bits too */
            }
            val = abs(val) ^ mask;
            if (max_peak[c] < val)
                max_peak[c] = val;
            valp += 3;
            if (vumeter == VUMETER_STEREO)
                c = !c;
        }
        break;
    }
    case 32: {
        signed int *valp = (signed int *)data;
        signed int mask = snd_pcm_format_silence_32(hwparams.format);

        count /= 4;
        c = 0;
        while (count-- > 0) {
            if (format_little_endian)
                val = __le32_to_cpu(*valp);
            else
                val = __be32_to_cpu(*valp);
            val = abs(val) ^ mask;
            if (max_peak[c] < val)
                max_peak[c] = val;
            valp++;
            if (vumeter == VUMETER_STEREO)
                c = !c;
        }
        break;
    }
    default:
        if (run == 0) {
            fprintf(stderr, _("Unsupported bit size %d.\n"), (int)bits_per_sample);
            run = 1;
        }
        return;
    }
    max = 1 << (bits_per_sample-1);
    if (max <= 0)
        max = 0x7fffffff;

    for (c = 0; c < ichans; c++) {
        if (bits_per_sample > 16)
            perc[c] = max_peak[c] / (max / 100);
        else
            perc[c] = max_peak[c] * 100 / max;
    }

    if (interleaved && verbose <= 2) {
        static int maxperc[2];
        static time_t t=0;
        const time_t tt=time(NULL);
        if(tt>t) {
            t=tt;
            maxperc[0] = 0;
            maxperc[1] = 0;
        }
        for (c = 0; c < ichans; c++)
            if (perc[c] > maxperc[c])
                maxperc[c] = perc[c];

        putchar('\r');
        print_vu_meter(perc, maxperc);
        fflush(stdout);
    }
    else if(verbose==3) {
        printf(_("Max peak (%li samples): 0x%08x "), (long)ocount, max_peak[0]);
        for (val = 0; val < 20; val++)
            if (val <= perc[0] / 5)
                putchar('#');
            else
                putchar(' ');
        printf(" %i%%\n", perc[0]);
        fflush(stdout);
    }
}



  print_vu_meter


static void print_vu_meter_mono(int perc, int maxperc)
{
    const int bar_length = 50;
    char line[80];
    int val;

    for (val = 0; val <= perc * bar_length / 100 && val < bar_length; val++)
        line[val] = '#';
    for (; val <= maxperc * bar_length / 100 && val < bar_length; val++)
        line[val] = ' ';
    line[val] = '+';
    for (++val; val <= bar_length; val++)
        line[val] = ' ';
    if (maxperc > 99)
        sprintf(line + val, "| MAX");
    else
        sprintf(line + val, "| %02i%%", maxperc);
    fputs(line, stdout);
    if (perc > 100)
        printf(_(" !clip  "));
}

最佳答案

看起来对此没有很大的兴趣,但是我想我会为将来发布答案,以防其他人尝试研究此类项目。

发现:


arecord只是aplay的链接副本
您可以使用令人难以置信的connectionPi c库向C代码添加线程
通过在代码中添加一个静态的volatile int变量-它在线程和主程序之间共享
将变量设置为perc值意味着它会在线程程序中立即更新


我可以使用以下代码通过LED模拟6电平音频电平表:

我使用面包板上的按钮在显示的LED电平和不显示的LED电平之间切换。

setAudioLEDS线程功能:

PI_THREAD (setAudioLEDs)
{
    // Only update LEDS if button is pressed
    // Gets Audio Level from global var: globalAudioLevel

    // Wiring Pi Constants for led and button
    // Pin number declarations. We're using the Broadcom chip pin numbers.

#define CYCLE_UPDATE '0'
#define CYCLE_STEADY '1'

    int last_button;
    int last_cycle;
    int this_cycle;

    // Button is released if this returns 1
    // HIGH or LOW (1 or 0)
    last_button = digitalRead(butPin);
    last_cycle = CYCLE_STEADY;
    this_cycle = last_cycle;

    while (1)
    {
        if (digitalRead(butPin) != last_button) {
            if (last_cycle == CYCLE_UPDATE)
                this_cycle = CYCLE_STEADY;
            else
                this_cycle = CYCLE_UPDATE;
            last_cycle = this_cycle;
        }

        switch (this_cycle) {

        case CYCLE_UPDATE:

            // Set LEDS based on audio level
            if (globalAudioLevel > 20)
                digitalWrite(led1, HIGH); // Turn LED ON
            else
                digitalWrite(led1, LOW); // Turn LED OFF

            if (globalAudioLevel > 40)
                digitalWrite(led2, HIGH); // Turn LED ON
            else
                digitalWrite(led2, LOW); // Turn LED OFF

            if (globalAudioLevel > 60)
                digitalWrite(led3, HIGH); // Turn LED ON
            else
                digitalWrite(led3, LOW); // Turn LED OFF

            if (globalAudioLevel > 70)
                digitalWrite(led4, HIGH); // Turn LED ON
            else
                digitalWrite(led4, LOW); // Turn LED OFF

            if (globalAudioLevel > 80)
                digitalWrite(led5, HIGH); // Turn LED ON
            else
                digitalWrite(led5, LOW); // Turn LED OFF

            if (globalAudioLevel > 90)
                digitalWrite(led6, HIGH); // Turn LED ON
            else
                digitalWrite(led6, LOW); // Turn LED OFF

            break;

        default:
            /* Button hasn't been pressed */
            digitalWrite(led1, LOW); // Turn LED OFF
            digitalWrite(led2, LOW); // Turn LED OFF
            digitalWrite(led3, LOW); // Turn LED OFF
            digitalWrite(led4, LOW); // Turn LED OFF
            digitalWrite(led5, LOW); // Turn LED OFF
            digitalWrite(led6, LOW); // Turn LED OFF
        }
    }
}

关于c - 修改ALSA arecord功能以将音频电平输出到Raspberry Pi 3 RGB LED,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38174727/

10-10 13:40