きっかけ
ネットで「Make a Web-Radio for Less Than $15」というサイトを見つけ、その記事の中で、MAX98357A という廉価な DAC (Digital to Analog Converter)があることを知った。ちょうど手元に ESP32 があるので、試してみた。
ライブラリーでハマる
前述のサイトではリンクが切れていたりして、ソースを探したら、簡単にできるものがあって、ほぼ「Audio.h」というライブラリーを使うだけで良さそうだったので、ArduinoIDE のライブラリーマネージャで Audio.h をインストールしてコンパイルしたら、Audio というタイプが存在しないというエラーになった。エラーを遡るとこのボード(ESP32)にライブラリーが対応していないという感じのエラーメッセージがあった。
見つけたライブラリー(重要)
ネット検索で ESP32-audioI2S が見つかり、zip ファイルをダウンロードして組み込んだら、ちゃんとコンパイルが通った。(ESP32を使う場合は要注意!)
ストリーミングに繋がらない
上記のライブラリーのサンプルに記載されているサイトは、全て繋がりませんでした。
あ、一番下のドイツ語を音声にする部分はしゃべってくれたので、配線は問題ないと確認できた。ドイツ語を翻訳アプリで英語にして言語種別を en にすると、ちゃんと英語で話した(笑)
繋がるところが見つかる!
ESP32_MP3_Decoder 中の playlist.pls に記載されている SomaFM が繋がって番組がスピーカーから流れた!
Web Radio のリスト
ネットを調べると、Community Radio Station Indexという便利なサイトが見つかった!
日本にある局を CSV 形式で欲しい時はブラウザーで、
http://95.179.139.106/csv/stations/bycountry/japan
とアクセスすると CSV が得られるので、Excel 等に取り込んで欲しい列だけ残して保存しておけば、聞きたい局のURLをソースに書き込めばOKだ。
更にこのAPIを使ったradio-browser というサイトがあって、ここでは視聴して好みの局を探してそのURLを見つけることができるので、お勧めだ。
プログラムのソース
とりあえず、動いたソースを貼っておきます。
繋がった曲をいくつか配列にして、局の指定は固定していますが、後で、ボタンで選局できるようにするつもりです。
(ご指摘などコメント歓迎)
# 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 プリンターで、見栄え&音質改善できるケースを作成する。