ESP32 でインターネットラジオ（Web Radio）を作る（ハマったこと）

## きっかけ
　ネットで[「Make a Web-Radio for Less Than $15」](https://www.instructables.com/Make-a-Web-Radio-for-Less-That-15/)というサイトを見つけ、その記事の中で、MAX98357A という廉価な DAC (Digital to Analog Converter)があることを知った。ちょうど手元に ESP32 があるので、試してみた。
![IMG_7067D.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16491/fc0648f2-c4c7-2a9f-46f3-34ae51348bef.jpeg)


## ライブラリーでハマる
　前述のサイトではリンクが切れていたりして、ソースを探したら、簡単にできるものがあって、ほぼ「Audio.h」というライブラリーを使うだけで良さそうだったので、ArduinoIDE のライブラリーマネージャで Audio.h をインストールしてコンパイルしたら、Audio というタイプが存在しないというエラーになった。エラーを遡るとこのボード（ESP32）にライブラリーが対応していないという感じのエラーメッセージがあった。

### 見つけたライブラリー（重要）
　ネット検索で [ESP32-audioI2S](https://github.com/schreibfaul1/ESP32-audioI2S) が見つかり、zip ファイルをダウンロードして組み込んだら、ちゃんとコンパイルが通った。（ESP32を使う場合は要注意！）

## ストリーミングに繋がらない
 上記のライブラリーのサンプルに記載されているサイトは、全て繋がりませんでした。
あ、一番下のドイツ語を音声にする部分はしゃべってくれたので、配線は問題ないと確認できた。ドイツ語を翻訳アプリで英語にして言語種別を en にすると、ちゃんと英語で話した（笑）

## 繋がるところが見つかる！
　[ESP32_MP3_Decoder 中の playlist.pls](https://github.com/MrBuddyCasino/ESP32_MP3_Decoder/blob/master/main/playlist.pls) に記載されている SomaFM が繋がって番組がスピーカーから流れた！

## Web Radio のリスト
　ネットを調べると、[Community Radio Station Index](https://nl1.api.radio-browser.info)という便利なサイトが見つかった！
　日本にある局を CSV 形式で欲しい時はブラウザーで、
```http://95.179.139.106/csv/stations/bycountry/japan``` 　
とアクセスすると CSV が得られるので、Excel 等に取り込んで欲しい列だけ残して保存しておけば、聞きたい局のURLをソースに書き込めばOKだ。
　更にこのAPIを使った[radio-browser](https://www.radio-browser.info/) というサイトがあって、ここでは視聴して好みの局を探してそのURLを見つけることができるので、お勧めだ。

## プログラムのソース
　とりあえず、動いたソースを貼っておきます。
　繋がった曲をいくつか配列にして、局の指定は固定していますが、後で、ボタンで選局できるようにするつもりです。
（ご指摘などコメント歓迎）

```cpp:WebRadioESP32.ino
#include "Arduino.h"
#include "WiFi.h"
// Librarry zip install from: https://github.com/schreibfaul1/ESP32-audioI2S
#include "Audio.h"

// Digital I/O used
#define I2S_DOUT      25  // DIN connection
#define I2S_BCLK      27  // Bit clock
#define I2S_LRC       26  // Left Right Clock
 
Audio audio;
 
String ssid =     "ynAir_G";
String password = "tsubasahikaru";
String stations[] ={
        "ice1.somafm.com/illstreet-128-mp3",      // SomaFM / Illinois Street Lounge
        "ais-sa2.cdnstream1.com/b22139_128mp3",   // 101 SMOOTH JAZZ
        "relax.stream.publicradio.org/relax.mp3", // Your Classical - Relax
        "16963.live.streamtheworld.com/SAM03AAC226_SC",    // #1980s Zoom
        "ice1.somafm.com/secretagent-128-mp3",    // SomaFM / Secret Agent
        "ice1.somafm.com/seventies-128-mp3",      // SomaFM / Left Coast 70s
        "ice1.somafm.com/bootliquor-128-mp3",     // SomaFM / Boot Liquor
        "musicbird.leanstream.co/JCB032-MP3",     // 84.3 FM Edogawa (FMえどがわ, JOZZ3AS-FM, Edogawa City,...
        "musicbird.leanstream.co/JCB093-MP3",     // Dreams FM (ドリームスエフエム, JOZZ0AI-FM, 76.5 MHz, Kurume...
        "musicbird.leanstream.co/JCB104-MP3",     // Kyoto Living FM (京都リビング FM/きょうと りびんぐ FM)
        "musicbird.leanstream.co/JCB015-MP3",     // FM Blue Shonan (FM・ブルー湘南 , JOZZ3AD-FM, 78.5 MHz, Y...
};

uint8_t cur_station  = 2;         // current station No.

void setup() {
    Serial.begin(115200);
    WiFi.disconnect();
    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid.c_str(), password.c_str());
    while (WiFi.status() != WL_CONNECTED) delay(1500);
    Serial.println("WiFi start");
    audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
    audio.setVolume(15); // 0...21
    
//    audio.connecttospeech("Wenn die Hunde schlafen, kann der Wolf gut Schafe stehlen.", "de");
//    audio.connecttospeech("When the dogs sleep, the wolf is good at stealing sheep.", "en");

    audio.connecttohost(stations[cur_station].c_str());

}
 
void loop()
{
    audio.loop();
}
 
// optional
void audio_info(const char *info){
    Serial.print("info        "); Serial.println(info);
}
void audio_id3data(const char *info){  //id3 metadata
    Serial.print("id3data     ");Serial.println(info);
}
void audio_eof_mp3(const char *info){  //end of file
    Serial.print("eof_mp3     ");Serial.println(info);
}
void audio_showstation(const char *info){
    Serial.print("station     ");Serial.println(info);
}
void audio_showstreaminfo(const char *info){
    Serial.print("streaminfo  ");Serial.println(info);
}
void audio_showstreamtitle(const char *info){
    Serial.print("streamtitle ");Serial.println(info);
}
void audio_bitrate(const char *info){
    Serial.print("bitrate     ");Serial.println(info);
}
void audio_commercial(const char *info){  //duration in sec
    Serial.print("commercial  ");Serial.println(info);
}
void audio_icyurl(const char *info){  //homepage
    Serial.print("icyurl      ");Serial.println(info);
}
void audio_lasthost(const char *info){  //stream URL played
    Serial.print("lasthost    ");Serial.println(info);
}
void audio_eof_speech(const char *info){
    Serial.print("eof_speech  ");Serial.println(info);
}
```

## 今後は
　ボタンで局を順送りにできるようにするかな?
　3D プリンターで、見栄え＆音質改善できるケースを作成する。