Advertisement
zefie

Cheap HDRadio to Icecast thing w/ Metadata (using RTLSDR)

Aug 21st, 2017
562
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 4.90 KB | None | 0 0
  1. #!/usr/bin/php
  2. <?php
  3. // Quick alpha-quality code
  4. // Uses command line tools to decode an HD Radio stream via RTL-SDR, then encode it for Icecast Streaming
  5. //
  6. // Tools used: PHP (duh), RTLSDR, nrsc5, ffmpeg, ezstream, Icecast
  7.  
  8. $debug = 0;
  9. $ppm = 19;
  10. $bitrate = 256;
  11. $metafile = "/home/zefie/.config/.hdradio_meta";
  12.  
  13. $signal = 0;
  14. $oldtitle = "";
  15. $oldartist = "";
  16. $buffdat = "";
  17. $totalrcv = 0;
  18. $totalsnd = 0;
  19. $rate = 1024;
  20.  
  21. // Program direction (aka if program is gonna send data to a pipe (write), use "w")
  22. $desc = array(
  23.    0 => array("pipe", "r"),
  24.    1 => array("pipe", "w"),
  25.    2 => array("pipe", "w")
  26. );
  27.  
  28. $cwd = '/home/zefie';
  29. if (@$argv[1] && @$argv[2] !== null) {
  30.     if (@$argv[3] !== null) {
  31.         $gain = intval($argv[3] * 10);
  32.     } else {
  33.         $gain = 480;
  34.     }
  35.     $freq = intval($argv[1] * 1000000);
  36.     $prog = intval($argv[2]);
  37. } else {
  38.         echo "Usage: ".$_SERVER['PHP_SELF']." <freq> <program> [gain]\n";
  39.         echo "Example: ".$_SERVER['PHP_SELF']." 99.5 0 48.0\n";
  40.         exit(1);
  41. }
  42.  
  43. $hdradio = proc_open('nrsc5 -l 1 -g '.$gain.' -p '.$ppm.' -o - -f adts '.$freq.' '.$prog, $desc, $radio_pipes, $cwd);
  44. echo "Searching for HD Radio Signal on ".floatval($freq / 1000000)."MHz...\n";
  45.  
  46. if (is_resource($hdradio)) {
  47.     $hdradio_status = proc_get_status($hdradio);
  48.     if ($debug) echo "Decoder PID: ".$hdradio_status['pid']."\n";
  49.     stream_set_blocking($radio_pipes[1], 0);
  50.     stream_set_blocking($radio_pipes[2], 0);
  51.     while(true) {
  52.         if ($signal) {
  53.             if (is_resource(@$encoder) && is_resource(@$streamer)) {
  54.                 $decdata = fread($radio_pipes[1],$rate);
  55.                 if (strlen($decdata) > 0) {
  56.                     fwrite($encoder_pipes[0],$decdata);
  57.                 }
  58.                 $strdata = fread($encoder_pipes[1],(($bitrate / 8) * 1024) + 128); // try to keep up, eh?
  59.                 if (strlen($strdata) > 0) {
  60.                     fwrite($streamer_pipes[0],$strdata);
  61.                 }
  62.                
  63.                 $totalrcv = $totalrcv + strlen($decdata);
  64.                 $totalsnd = $totalsnd + strlen($strdata);
  65.             } else {                   
  66.                 $encoder = proc_open('ffmpeg -loglevel panic -i /dev/stdin -c:a vorbis -b:a '.$bitrate.'k -ar 44100 -f ogg -strict -2 -', $desc, $encoder_pipes, $cwd);
  67.                 if (is_resource($encoder)) {
  68.                     $encoder_status = proc_get_status($encoder);
  69.                     if ($debug) echo "Encoder PID: ".$encoder_status['pid']."\n";
  70.                     stream_set_blocking($encoder_pipes[0], 0);
  71.                     stream_set_blocking($encoder_pipes[1], 0);
  72.                 }
  73.                 $streamer = proc_open('ezstream -n -c /home/zefie/.config/ezstream_hdradio.cfg', $desc, $streamer_pipes, $cwd);
  74.                 if (is_resource($streamer)) {
  75.                     $streamer_status = proc_get_status($streamer);
  76.                     if ($debug) echo "Streamer PID: ".$streamer_status['pid']."\n";    
  77.                     stream_set_blocking($streamer_pipes[0], 0);
  78.                 }
  79.             }
  80.         }
  81.        
  82.         $radiodata = fread($radio_pipes[2],1024);
  83.         while (substr($radiodata,strlen($radiodata)-1,1) != PHP_EOL) {
  84.             $radiodata .= fread($radio_pipes[2],1);
  85.         }
  86.         if ($debug) echo $radiodata;       
  87.         $radiodata = preg_split("/\n/",$radiodata);
  88.         foreach ($radiodata as $r) {
  89.             if (strpos($r,"rtlsdr_open error") > 0) {
  90.                 clearLine();
  91.                 echo $r."\n";
  92.                 exit(1);
  93.             }
  94.            
  95.             if (strpos($r,"Synchronized") > 0) {
  96.                 $signal = 1;
  97.                 clearLine();
  98.                 echo "Found HDRadio Signal\n";
  99.             }
  100.            
  101.             if (strpos($r,"lost sync") > 0) {
  102.                 $signal = 0;
  103.                 clearLine();
  104.                 echo "Lost HDRadio Signal\n";
  105.             }
  106.  
  107.             if (strpos($r,": MER:") > 0) {
  108.                 $a = (strpos($r,": MER:") + 7);
  109.                 $b = strlen($r) - $a;
  110.                 $siglvl = substr($r,$a,$b);
  111.             }
  112.            
  113.             if (strpos($r,": Title:") > 0) {
  114.                 $a = (strpos($r,": Title:") + 9);
  115.                 $b = strlen($r) - $a;
  116.                 $title = substr($r,$a,$b);
  117.             }
  118.            
  119.             if (strpos($r,": Artist:") > 0) {
  120.                 $a = (strpos($r,": Artist:") + 10);
  121.                 $b = strlen($r) - $a;
  122.                 $artist = substr($r,$a,$b);
  123.             }
  124.         }
  125.         if ((@$artist != $oldartist) && (@$title != $oldtitle)) {
  126.             $oldartist = $artist;
  127.             $oldtitle = $title;
  128.             clearLine();
  129.             echo "Song: ".$artist." - ".$title."\n";
  130.             $fp = fopen($metafile,"w");
  131.             fwrite($fp,$artist."\n".$title);
  132.             fclose($fp);
  133.             posix_kill($streamer_status['pid'],12); // SIGUSR2
  134.         }
  135.        
  136.         if ($signal) {
  137.             if (@$siglvl) {
  138.                 echo "Signal: ".$siglvl." | ";
  139.             }
  140.             echo "FM Recv'd: ".friendlyBytes($totalrcv)." | INet Sent: ".friendlyBytes($totalsnd);
  141.             echo "   \r";
  142.         } else {
  143.             sleep(1);
  144.         }
  145.     }
  146. }
  147.  
  148. function getScreenWidth() {
  149.     preg_match_all("/rows.([0-9]+);.columns.([0-9]+);/", strtolower(exec('stty -a |grep columns')), $output);
  150.     if(sizeof($output) == 3) {
  151.         return $output[2][0];
  152.     }
  153. }
  154.  
  155. function clearLine() {
  156.     for ($i=0; $i<(getScreenWidth()-1); $i++) {
  157.         echo " ";
  158.     }
  159.     echo "\r";
  160. }
  161.  
  162. function friendlyBytes($size) {
  163.         if ($size > 1073741824) {
  164.                 return round(($size / 1073741824),2)."GB";
  165.         }
  166.         if ($size > 1048576) {
  167.                 return round(($size / 1048576),2)."MB";
  168.         }
  169.         if ($size > 1024) {
  170.                 return round(($size / 1024),2)."KB";
  171.         }
  172.         return $size."B";
  173. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement