2016-07-03 2 views
0

Je peux actuellement utiliser mon raspberry pi 3 pour rediriger USB Audio input vers un icecast stream. Actuellement, il fonctionne très bien dans les petits tests quand je pipe arecord from USB audio hw input to avconv (équivalent ffmpeg) sur Raspbian Jessie Lite. Arecord dispose d'un vu-mètre intégré pour les niveaux audio lorsque vous utilisez le réglage détaillé. Je pense que le code est situé dans la fonction ci-jointe. Je me demande s'il est possible de réécrire cette fonction pour la sortie Raspberry Pi 3 RVB LED - pour envoyer en quelque sorte le rouge/jaune/vert basé sur les niveaux de volume - en utilisant la variable de crête de la fonction?Modifier la fonction ALSA arecord pour sortir les niveaux audio à Raspberry Pi 3 RGB LED

J'ai inclus toute la fonction - et la fonction d'impression. Si cela pouvait être fait, je pense que le code pourrait probablement remplacer print_vu_meter(perc, maxperc);

Est-il possible de modifier arecord pour obtenir le Raspi 3 pour gérer le traitement pendant le tuyau? Est-il possible d'utiliser un autre thread?

Je ne suis pas dans ma ligue ici - je cherche juste un début, ou des idées pour sortir l'idée de ma tête ou dire que c'est possible.

gestionnaire pic

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 ")); 
} 
+0

Question: Est-il possible? Réponse: Oui, c'est possible. – immibis

Répondre

0

ne ressemble pas à cela, il y a beaucoup d'intérêt, mais je pensais que je serais poster mon un nswer pour l'avenir, au cas où quelqu'un d'autre essaye de plonger dans ce type de projet.

Résultats:

  • arecord est juste une copie liée de aplay
  • vous pouvez utiliser la bibliothèque incroyable wiringPi c pour ajouter un fil au code C
  • en ajoutant un volatile statique variable de type int à le code - il devient partagé avec thread et le programme principal
  • la définition de la variable à la valeur de perc signifie qu'il est mis à jour immédiatement dans le programme fileté

j'ai pu simuler un indicateur de niveau audio 6 niveaux avec LED en utilisant ce code:

J'ai utilisé un bouton sur la carte de test pour basculer entre les niveaux LED affiché et non.

setAudioLEDS fonction filetée:

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 
     } 
    } 
}