<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Lesson 6.1. Speaker. MP3 player]]></title><description><![CDATA[<h2>The purpose of this lesson</h2>
<p dir="auto">Hi! Today we will learn how to play audio files of MP3 format using the built-in DAC. Write a simple player (Fig. 1).</p>
<p dir="auto"><img src="https://pp.userapi.com/c847122/v847122789/7209/qTXTn-uzsco.jpg" alt="" class=" img-fluid img-markdown" /></p>
<p dir="auto">Figure 1. Welcome screen</p>
<h2>Brief theory</h2>
<p dir="auto"><strong>Digital-to-analog Converter (DAC)</strong> – a device for converting digital (usually binary) code into an analog signal (current, voltage or charge). Digital-to-analog converters are the interface between the discrete digital world and analog signals. The signal from DAC without interpolation on the background of an ideal signal is shown in figure 2.</p>
<p dir="auto"><img src="https://pp.userapi.com/c847122/v847122789/7228/tL0VrnLvOoc.jpg" alt="" class=" img-fluid img-markdown" /></p>
<p dir="auto">Figure 2</p>
<p dir="auto">In M5STACK the DAC outputs correspond to the 25 and contacts 26 (Fig. 2.1).</p>
<blockquote>
<p dir="auto">Note that the built-in speaker is connected to 25 pins in parallel. 26 the contact is free and can be used as a linear output. By default, both contacts are enabled, use AudioOutputI2S for configuration</p>
</blockquote>
<p dir="auto"><img src="https://pp.userapi.com/c847122/v847122789/7258/zDO0GxQQxxU.jpg" alt="" class=" img-fluid img-markdown" /></p>
<p dir="auto">Figure 2.1</p>
<p dir="auto"><strong>MP3</strong> audio of the third level, developed by a team of MPEG file format to store the audio information. MP3 is one of the most common and popular digital audio encoding formats. It is widely used in file sharing networks for evaluation download of music. The format can be played in almost all popular operating systems, on most portable audio players, and is supported by all modern models of the music centers and DVD players.</p>
<p dir="auto">More information on the Wiki: <a href="https://en.wikipedia.org/wiki/MP3" title="https://en.wikipedia.org/wiki/MP3" target="_blank" rel="noopener noreferrer nofollow ugc">https://en.wikipedia.org/wiki/MP3</a></p>
<p dir="auto">The development of libraries for ESP32 and ESP8266 to work with popular audio formats, including MP3, is the user GitHub <strong>earlephilhower</strong> <a href="https://github.com/earlephilhower" title="https://github.com/earlephilhower" target="_blank" rel="noopener noreferrer nofollow ugc">https://github.com/earlephilhower</a>, reference to the library <a href="https://github.com/earlephilhower/ESP8266Audio" title="https://github.com/earlephilhower/ESP8266Audio" target="_blank" rel="noopener noreferrer nofollow ugc">https://github.com/earlephilhower/ESP8266Audio</a></p>
<p dir="auto"><strong>List of components for the lesson</strong></p>
<ul>
<li>M5STACK;</li>
<li>USB-C cable.</li>
</ul>
<h2>Begin!</h2>
<h3>Step 1. Draw a sketch</h3>
<p dir="auto">Draw a sketch of our player (Fig. 3). The name of the previous, current and next track will be displayed at the bottom of the screen. The name of the current track will be made black standard font size 3. The side tracks will be grayed out in standard size 2 font. In the center of the screen will be a time line of gray color, which will move the red label. In the upper right corner add four gray pillars that mimic the sound spectrum. The album cover will be located in the left corner.</p>
<p dir="auto"><img src="https://pp.userapi.com/c847122/v847122789/7264/VQJZ64X4kps.jpg" alt="" class=" img-fluid img-markdown" /></p>
<p dir="auto">Figure 3. Sketch of the project</p>
<h3>Step 2. Logotype</h3>
<p dir="auto">Let's use the standard graphical editor to make a logo (Fig. 3.1), which will be displayed on the screen when you turn on the device.</p>
<p dir="auto"><img src="https://pp.userapi.com/c847122/v847122489/8479/lQuQikbXJfk.jpg" alt="" class=" img-fluid img-markdown" /></p>
<p dir="auto">Figure 3.1. The logo of the player</p>
<p dir="auto">Don't forget to convert and connect:</p>
<pre><code>extern unsigned char logo[];
</code></pre>
<p dir="auto">Let's draw our logo from the drawGUI () function of setup():</p>
<pre><code>void drawGUI() {
  M5.Lcd.drawBitmap(0, 0, 320, 150, (uint16_t *)logo);
  M5.Lcd.setTextColor(0x7bef);
  drawTrackList();
  while (true)
  {
    if (m5.BtnB.wasPressed())
    {
      M5.Lcd.fillRect(0, 0, 320, 240, 0x0000);
      M5.Lcd.fillRoundRect(0, 0, 320, 240, 7, 0xffff); 
      drawTrackList();
      break; 
    }
    m5.update();
  }
}
</code></pre>
<blockquote>
<p dir="auto">Please note that I use the design to work with the SD card-I told about it in the 5th lesson.</p>
</blockquote>
<pre><code>void setup(){
  M5.begin();
  WiFi.mode(WIFI_OFF);
  M5.Lcd.fillRoundRect(0, 0, 320, 240, 7, 0xffff);
  M5.Lcd.setTextColor(0x7bef);
  M5.Lcd.setTextSize(2);
  M5.Lcd.drawBitmap(30, 75, 59, 59, (uint16_t *)timer_logo);
  M5.Lcd.setCursor(110, 90);
  M5.Lcd.print("STARTING...");
  M5.Lcd.setCursor(110, 110);
  M5.Lcd.print("WAIT A MOMENT");
  if (!SD.begin())
  {
    M5.Lcd.fillRoundRect(0, 0, 320, 240, 7, 0xffff);
    M5.Lcd.drawBitmap(50, 70, 62, 115, (uint16_t *)insertsd_logo);
    M5.Lcd.setCursor(130, 70);
    M5.Lcd.print("INSERT");
    M5.Lcd.setCursor(130, 90);
    M5.Lcd.print("THE TF-CARD");
    M5.Lcd.setCursor(130, 110);
    M5.Lcd.print("AND TAP");
    M5.Lcd.setCursor(130, 130);
    M5.Lcd.setTextColor(0xe8e4);
    M5.Lcd.print("POWER");
    M5.Lcd.setTextColor(0x7bef);
    M5.Lcd.print(" BUTTON"); 
    while(true);
  }
  if (!createTrackList("/"))
  {
    M5.Lcd.fillRoundRect(0, 0, 320, 240, 7, 0xffff);
    M5.Lcd.drawBitmap(30, 75, 59, 59, (uint16_t *)error_logo);
    M5.Lcd.setCursor(110, 70);
    M5.Lcd.print("ADD MP3 FILES");
    M5.Lcd.setCursor(110, 90);
    M5.Lcd.print("TO THE TF-CARD");
    M5.Lcd.setCursor(110, 110);
    M5.Lcd.print("AND TAP");
    M5.Lcd.setCursor(110, 130);
    M5.Lcd.setTextColor(0xe8e4);
    M5.Lcd.print("POWER");
    M5.Lcd.setTextColor(0x7bef);
    M5.Lcd.print(" BUTTON");
    while(true);
  }
  drawGUI();
  play('m');
}
</code></pre>
<h3>Step 3. Adding libraries</h3>
<p dir="auto">To use other libraries, you need to add it. You can download it in the appropriate paragraph in the section <strong>Download -&gt; Library</strong>. In order to add a library you need to launch Arduino IDE select the menu section Sketch -&gt; Include Library -&gt; Add .ZIP Library... (rice. 4, 4.1).</p>
<p dir="auto"><img src="https://pp.userapi.com/c847122/v847122447/c440/p5yLezNlmrg.jpg" alt="" class=" img-fluid img-markdown" /></p>
<p dir="auto">Figure 4. Adding a library in the Arduino IDE</p>
<p dir="auto"><img src="https://pp.userapi.com/c847122/v847122447/c438/ohpCITD0d74.jpg" alt="" class=" img-fluid img-markdown" /></p>
<p dir="auto">Figure 4.1. Required libraries into a ZIP-archive</p>
<p dir="auto">When libraries are added, you can attach them to a new project:</p>
<pre><code>#include &lt;M5Stack.h&gt;
#include &lt;WiFi.h&gt;
#include "AudioFileSourceSD.h"
#include "AudioFileSourceID3.h"
#include "AudioGeneratorMP3.h"
#include "AudioOutputI2S.h"
</code></pre>
<h3>Step 4. Use the engine. The case for MP3</h3>
<p dir="auto">Don't ask "what is it for?"-  we'll know it later:</p>
<pre><code>AudioGeneratorMP3 *mp3;
AudioFileSourceSD *file;
AudioOutputI2S *out;
AudioFileSourceID3 *id3; 
bool playing = true;
</code></pre>
<h3>Step 5. Make a playlist</h3>
<p dir="auto">Let's make a structure containing fields: label (path to mp3-file, the same track name), timePos - time (memory area) on which the track is paused, pointers to neighboring tracks left and right:</p>
<pre><code>struct Track
{
  String label;
  int timePos;
  Track *left;
  Track *right;
};
</code></pre>
<p dir="auto">Declare a dynamic list, in fact, our playlist:</p>
<pre><code>Track *trackList;
</code></pre>
<p dir="auto">To create a playlist, let's write a simple function that takes as an argument the path where MP3 files are located. If nothing is found, the function returns false:</p>
<pre><code>bool createTrackList(String dir) {
  int i = 0;
  File root = SD.open(strToChar(dir));
  if (root)
  {
    while (true)
    {
      File entry =  root.openNextFile();
      if (!entry) break;
      if (!entry.isDirectory())
      {
        String ext = parseString(cntChar(entry.name(), '.'), '.', entry.name());
        if (ext == "mp3") 
        {
          i++;
          Track *tmp = new Track;
          tmp-&gt;label = entry.name();
          tmp-&gt;timePos = 0;
          tmp-&gt;right = tmp; 
          if (trackList == NULL)
          {
            tmp-&gt;left = tmp;
            trackList = tmp;
          }
          else
          {
            tmp-&gt;left = trackList;
            trackList-&gt;right = tmp;
            trackList = trackList-&gt;right;
          }
        }
      }
      entry.close();
    }
    if (i &gt; 1)
    {
      do
      {
        trackList = trackList-&gt;left;
      } while(trackList != trackList-&gt;left);
    }
    root.close();
  }
  if (i &gt; 0)
    return true;
  return false;
}
</code></pre>
<blockquote>
<p dir="auto">Note that the leftmost and rightmost tracks are self-contained, not NULL</p>
</blockquote>
<h3>Step 6. Tracklist drawing is easy!</h3>
<pre><code>String labelCut(int from, int to, String str) {    
  String tmp = str.substring(1, posChar(str, '.'));
  if (str.length() &gt; to)
    tmp = tmp.substring(from, to);
  return tmp;
}

void drawTrackList() {
  M5.Lcd.fillRect(0, 130, 320, 75, 0xffff);

  if (trackList-&gt;left != trackList)
  {
    M5.Lcd.setTextSize(2);
    M5.Lcd.setTextColor(0x7bef);
    M5.Lcd.setCursor(10, 130);
    M5.Lcd.print(labelCut(0, 22, (trackList-&gt;left)-&gt;label));
  }
 
  M5.Lcd.setTextSize(3); 
  M5.Lcd.setTextColor(0x0000);
  M5.Lcd.setCursor(10, 155);
  M5.Lcd.print(labelCut(0, 16, (trackList-&gt;label)));

  if (trackList-&gt;right != trackList)
  {
    M5.Lcd.setTextSize(2);
    M5.Lcd.setTextColor(0x7bef);
    M5.Lcd.setCursor(10, 185);
    M5.Lcd.print(labelCut(0, 22, (trackList-&gt;right)-&gt;label));
  }
}
</code></pre>
<h3>Step 7. Timeline</h3>
<pre><code>unsigned long drawTimeline_previousMillis = 0;
void drawTimeline() {
  currentMillis = millis();
  if (currentMillis - drawTimeline_previousMillis &gt; 250)
  {
    int x = 30;
    int y = 110;
    int width = 260;
    int heightLine = 2;
    int heightMark = 20;
    int widthMark = 2;
    int yClear = y - (heightMark / 2);
    int wClear = width + (widthMark / 2);
    
    drawTimeline_previousMillis = currentMillis;
    M5.Lcd.fillRect(x, yClear, wClear, heightMark, 0xffff);
    M5.Lcd.fillRect(x, y, width, heightLine, 0x7bef);
    int size_ = id3-&gt;getSize();
    int pos_ = id3-&gt;getPos();
    int xPos = x + ((pos_ * (width - (widthMark / 2))) / size_);
    M5.Lcd.fillRect(xPos, yClear, widthMark, heightMark, 0xe8e4);
  }
}
</code></pre>
<h3>Step 8. Spectrum emulator</h3>
<pre><code>unsigned long genSpectrum_previousMillis = 0;
void genSpectrum() {
  currentMillis = millis();
  if (currentMillis - genSpectrum_previousMillis &gt; 100)
  {
    genSpectrum_previousMillis = currentMillis;
    drawSpectrum(random(0,101), random(0,101), random(0,101), random(0,101));
  }
}

void drawSpectrum(int a, int b, int c, int d) { // %
  int x = 195;
  int y = 30;
  int padding = 10;
  int height = 30;
  int width = 15;

  int aH = ((a * height) / 100);
  int aY = y + (height - aH);
  M5.Lcd.fillRect(x, y, width, height, 0xffff);
  M5.Lcd.fillRect(x, aY, width, aH, 0x7bef); //0xe8e4
  
  int bH = ((b * height) / 100);
  int bY = y + (height - bH);
  int bX = x + width + padding;
  M5.Lcd.fillRect(bX, y, width, height, 0xffff);
  M5.Lcd.fillRect(bX, bY, width, bH, 0x7bef); //0xff80

  int cH = ((c * height) / 100);
  int cY = y + (height - cH);
  int cX = bX + width + padding;
  M5.Lcd.fillRect(cX, y, width, height, 0xffff);
  M5.Lcd.fillRect(cX, cY, width, cH, 0x7bef);//0x2589

  int dH = ((d * height) / 100);
  int dY = y + (height - dH);
  int dX = cX + width + padding;;
  M5.Lcd.fillRect(dX, y, width, height, 0xffff);
  M5.Lcd.fillRect(dX, dY, width, dH, 0x7bef);//0x051d
}
</code></pre>
<h3>Step 9. Work with engine MP3</h3>
<p dir="auto">In order to play MP3's from a playlist write a function Play(char), which as argument takes the instruction. If the argument is set to' l', the pointer in the dynamic list will be shifted to the left and the track will start playing on the left. Similarly for the track on the right. If the argument is set to' m', it means play back silence. If you pass any other argument, it would mean 't' (this) - play current, i.e. the one pointed to by the pointer.</p>
<pre><code>bool play(char dir) {
  switch (dir)
  {
    case 'r':
      if (trackList == trackList-&gt;right) return false;
      trackList-&gt;timePos = 0;
      trackList = trackList-&gt;right;       
    break;
    case 'l':
    if (trackList == trackList-&gt;left) return false;
      trackList-&gt;timePos = 0;
      trackList = trackList-&gt;left;
    break;
    case 'm': // mute
      delete file;
      delete out;
      delete mp3;
      mp3 = NULL;
      file = NULL;
      out = NULL;
      file = new AudioFileSourceSD("/");
      id3 = new AudioFileSourceID3(file);
      out = new AudioOutputI2S(0, 1);
      out-&gt;SetOutputModeMono(true);
      mp3 = new AudioGeneratorMP3();
      mp3-&gt;begin(id3, out);
      playing = false;
    return true;
    default:
      if (playing)
      {
        trackList-&gt;timePos = id3-&gt;getPos();
        play('m');
        return true;
      }
    break;
  }
  drawCover();
  mp3-&gt;stop();
  delete file;
  delete out;
  delete mp3;
  mp3 = NULL;
  file = NULL;
  out = NULL;
  file = new AudioFileSourceSD(strToChar(trackList-&gt;label));
  id3 = new AudioFileSourceID3(file);
  id3-&gt;seek(trackList-&gt;timePos, 1);
  out = new AudioOutputI2S(0, 1);
  out-&gt;SetOutputModeMono(true);
  mp3 = new AudioGeneratorMP3();
  mp3-&gt;begin(id3, out);
  playing = true;
  return true;
}
</code></pre>
<h3>Step 10. Loop</h3>
<pre><code>void loop(){ 
  if (m5.BtnA.wasPressed())
  {
    play('l');
    drawTrackList();
  }

  if (m5.BtnB.wasPressed())
  {
    play('t');
  }

  if (m5.BtnC.wasPressed())
  {
    play('r');
    drawTrackList();
  }
</code></pre>
<p dir="auto">the design below is subject to little change. We will add playback in order of play ('r'), pause control of playing, rendering of dynamic data of genSpectrum () and drawTimeline():</p>
<pre><code>  if (playing)
  {
    if (mp3-&gt;isRunning())
    {
      if (!mp3-&gt;loop())
      {
        mp3-&gt;stop();
        playing = false;
        play('r');
        drawTrackList();
      }
    }
    else
    {
      delay(1000);
    }
    genSpectrum();
    drawTimeline();
  }
  m5.update();
}
</code></pre>
<h3>Step 11. LAUNCH!</h3>
<p dir="auto">Everything works and looks good enough, the only thing is the crackle when switching songs. The cause has not yet been set.</p>
<p dir="auto"><img src="https://pp.userapi.com/c847122/v847122789/7219/Kz44bzF6I3w.jpg" alt="" class=" img-fluid img-markdown" /></p>
<p dir="auto">Figure 5. Playback screen</p>
<h3>Homework</h3>
<ul>
<li><strong>Task 1 level of difficulty</strong>: add control of the existence of the JPG files of the album artwork on TF card. If the album cover is missing, add a draft instead (you can download in <strong>Download - &gt; Images - &gt; HomeWork1</strong>);</li>
<li><strong>Task 2 difficulty levels</strong>: add a running line for long track titles.</li>
<li><strong>Task 3 difficulty level</strong>: use ID3 to extract the album cover from the MP3 file to avoid using external JPG files;</li>
<li><strong>Task 4 difficulty levels</strong>: instead of emulating the spectrum, implement a fast Fourier transform. The first pillar is 100 Hz, the second - 600 Hz, the third - 1500 Hz, the fourth 3000 Hz.</li>
</ul>
<h3>Download</h3>
<ul>
<li>
<p dir="auto">Video demonstration (YouTube): <a href="https://youtu.be/D6pnG0Ha0yw" title="https://youtu.be/D6pnG0Ha0yw" target="_blank" rel="noopener noreferrer nofollow ugc">https://youtu.be/D6pnG0Ha0yw</a></p>
</li>
<li>
<p dir="auto">Source codes (GitHub): <a href="https://github.com/dsiberia9s/mp3-player-m5stack" title="https://github.com/dsiberia9s/mp3-player-m5stack" target="_blank" rel="noopener noreferrer nofollow ugc">https://github.com/dsiberia9s/mp3-player-m5stack</a></p>
</li>
<li>
<p dir="auto">Image converters (Yandex Disk): <a href="https://yadi.sk/d/dOj_EyU_3TfhWV" title="https://yadi.sk/d/dOj_EyU_3TfhWV" target="_blank" rel="noopener noreferrer nofollow ugc">https://yadi.sk/d/dOj_EyU_3TfhWV</a></p>
</li>
<li>
<p dir="auto">Images (Yandex Disk): <a href="https://yadi.sk/d/_wGruXC73TfhZ6" target="_blank" rel="noopener noreferrer nofollow ugc">https://yadi.sk/d/_wGruXC73TfhZ6</a></p>
</li>
<li>
<p dir="auto">Library (Yandex Disk): <a href="https://yadi.sk/d/GX--lQ3v3Tfhcf" title="https://yadi.sk/d/GX--lQ3v3Tfhcf" target="_blank" rel="noopener noreferrer nofollow ugc">https://yadi.sk/d/GX--lQ3v3Tfhcf</a></p>
</li>
<li>
<p dir="auto">TF card files (Yandex Disk): <a href="https://yadi.sk/d/15YnN5tC3Tfhg5" title="https://yadi.sk/d/15YnN5tC3Tfhg5" target="_blank" rel="noopener noreferrer nofollow ugc">https://yadi.sk/d/15YnN5tC3Tfhg5</a></p>
</li>
</ul>
]]></description><link>https://community.m5stack.com/topic/143/lesson-6-1-speaker-mp3-player</link><generator>RSS for Node</generator><lastBuildDate>Tue, 28 Apr 2026 22:32:21 GMT</lastBuildDate><atom:link href="https://community.m5stack.com/topic/143.rss" rel="self" type="application/rss+xml"/><pubDate>Fri, 23 Mar 2018 09:20:11 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Lesson 6.1. Speaker. MP3 player on Thu, 21 Nov 2019 13:20:48 GMT]]></title><description><![CDATA[<p dir="auto">Hi <a class="plugin-mentions-user plugin-mentions-a" href="/user/dimi" aria-label="Profile: Dimi">@<bdi>Dimi</bdi></a>, thanks for the amazing tutorial.</p>
<p dir="auto">Can I ask a question?<br />
I want to make an m5stack program that would play an mp3 file if I send a trigger via UDP, and would stop if I send a different trigger via UDP.<br />
I followed some of your code.</p>
<p dir="auto">But when I sent the trigger, the mp3 only played the first second and kept repeating the same time position. It wouldn't play the entire mp3 song.</p>
<p dir="auto">This is the code that I used:</p>
<hr />
<p dir="auto">#include &lt;M5Stack.h&gt;<br />
#include &lt;WiFi.h&gt;<br />
#include &lt;WiFiUdp.h&gt;<br />
#include "AudioFileSourceSD.h"<br />
#include "AudioFileSourceID3.h"<br />
#include "AudioGeneratorMP3.h"<br />
#include "AudioOutputI2S.h"<br />
#define N 1024</p>
<p dir="auto">bool playing = true;<br />
AudioGeneratorMP3 *mp3;<br />
AudioFileSourceSD *file;<br />
AudioOutputI2S *out;<br />
AudioFileSourceID3 *id3;</p>
<p dir="auto">const char* ssid = "wifiname";<br />
const char* password = "wifipassword";<br />
const int port = 5555;</p>
<p dir="auto">// The udp library class<br />
WiFiUDP udp;</p>
<p dir="auto">void print_wifi_state(){<br />
M5.Lcd.clear(BLACK);  // clear LCD<br />
M5.Lcd.setTextColor(YELLOW);<br />
M5.Lcd.setCursor(3, 3);<br />
M5.Lcd.println("");<br />
M5.Lcd.println("WiFi connected.");<br />
M5.Lcd.print("IP address: ");<br />
M5.Lcd.println(WiFi.localIP());<br />
M5.Lcd.print("Port: ");<br />
M5.Lcd.println(port);<br />
}</p>
<p dir="auto">void setup_wifi(){<br />
M5.Lcd.setTextColor(RED);<br />
M5.Lcd.setTextSize(2);<br />
M5.Lcd.setCursor(3, 10);<br />
M5.Lcd.print("Connecting to ");<br />
M5.Lcd.println(ssid);</p>
<p dir="auto">// setup wifi<br />
WiFi.mode(WIFI_STA);  // WIFI_AP, WIFI_STA, WIFI_AP_STA or WIFI_OFF<br />
WiFi.begin(ssid, password);<br />
// WiFi.begin();</p>
<p dir="auto">// Connecting ..<br />
while (WiFi.status() != WL_CONNECTED) {<br />
delay(100);<br />
M5.Lcd.print(".");<br />
}</p>
<p dir="auto">// print state<br />
print_wifi_state();</p>
<pre><code>udp.begin(port);
</code></pre>
<p dir="auto">}</p>
<p dir="auto">void setup() {<br />
M5.begin();<br />
M5.Speaker.setVolume(5);<br />
play('m');<br />
// setup wifi<br />
setup_wifi();</p>
<p dir="auto">}</p>
<p dir="auto">bool play(char dir){<br />
switch(dir)<br />
{<br />
case 'm':<br />
delete file;<br />
delete out;<br />
delete mp3;<br />
mp3 = NULL;<br />
file = NULL;<br />
out = NULL;<br />
file = new AudioFileSourceSD("/");<br />
id3 = new AudioFileSourceID3(file);<br />
out = new AudioOutputI2S(0, 1);<br />
out-&gt;SetOutputModeMono(true);<br />
mp3 = new AudioGeneratorMP3();<br />
mp3-&gt;begin(id3, out);<br />
playing = false;<br />
return true;<br />
default:<br />
if(playing){<br />
play('m');<br />
return true;<br />
}<br />
break;<br />
}<br />
mp3-&gt;stop();<br />
delete file;<br />
delete out;<br />
delete mp3;<br />
mp3 = NULL;<br />
file = NULL;<br />
out = NULL;<br />
file = new AudioFileSourceSD("/RainDrizzle.mp3");<br />
id3 = new AudioFileSourceID3(file);<br />
id3-&gt;seek(trackList-&gt;timePos, 1);<br />
out = new AudioOutputI2S(0, 1);<br />
out-&gt;SetOutputModeMono(true);<br />
mp3 = new AudioGeneratorMP3();<br />
mp3-&gt;begin(id3, out);<br />
playing = true;</p>
<p dir="auto">return true;<br />
}</p>
<p dir="auto">void loop() {<br />
char packetBuffer[N];<br />
int packetSize = udp.parsePacket();</p>
<p dir="auto">// get packet<br />
if (packetSize){</p>
<pre><code>int len = udp.read(packetBuffer, packetSize);

if (len &gt; 0){
  packetBuffer[len] = '\0'; // end
}
</code></pre>
<p dir="auto">}</p>
<pre><code>if(strcmp(packetBuffer,"start")==0){
// print param
M5.Lcd.clear(BLACK);
M5.Lcd.setCursor(3, 3);
M5.Lcd.setTextColor(GREEN);
M5.Lcd.println(packetBuffer);

play('t');

}

if(strcmp(packetBuffer,"stop")==0){
M5.Lcd.clear(BLACK);
M5.Lcd.setCursor(3, 3);
M5.Lcd.setTextColor(GREEN);
M5.Lcd.println(packetBuffer);
play('m');
}

if(playing){
  if(mp3-&gt;isRunning()){
    if(!mp3-&gt;loop()){
      mp3-&gt;stop();
      playing = false;
    }
  }
  else{
    delay(1000);
  }
</code></pre>
<p dir="auto">}<br />
M5.update();<br />
}</p>
<hr />
<p dir="auto">Thank you in advance.</p>
]]></description><link>https://community.m5stack.com/post/6469</link><guid isPermaLink="true">https://community.m5stack.com/post/6469</guid><dc:creator><![CDATA[creativetabi]]></dc:creator><pubDate>Thu, 21 Nov 2019 13:20:48 GMT</pubDate></item><item><title><![CDATA[Reply to Lesson 6.1. Speaker. MP3 player on Thu, 17 Oct 2019 18:01:32 GMT]]></title><description><![CDATA[<p dir="auto">He <a class="plugin-mentions-user plugin-mentions-a" href="/user/dimi" aria-label="Profile: Dimi">@<bdi>Dimi</bdi></a> , this is a great tutorial on creating a fantastic little music player!<br />
I'm looking to use my m5Stack in my car, connected to the aux in of my stereo.<br />
I'd also like to incorporate a mode to stream audio via Bluetooth from my phone,  but that'll take a fair bit of further homework to get working 😂</p>
]]></description><link>https://community.m5stack.com/post/6032</link><guid isPermaLink="true">https://community.m5stack.com/post/6032</guid><dc:creator><![CDATA[craighissett]]></dc:creator><pubDate>Thu, 17 Oct 2019 18:01:32 GMT</pubDate></item><item><title><![CDATA[Reply to Lesson 6.1. Speaker. MP3 player on Tue, 27 Mar 2018 04:58:19 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/m5dude" aria-label="Profile: m5dude">@<bdi>m5dude</bdi></a> <a class="plugin-mentions-user plugin-mentions-a" href="/user/m5dude" aria-label="Profile: m5dude">@<bdi>m5dude</bdi></a> use 26, 25 is occupied by built-in speaker. Yes, use ordinary headphones and everything will work. just be careful not to spoil your hearing!</p>
]]></description><link>https://community.m5stack.com/post/665</link><guid isPermaLink="true">https://community.m5stack.com/post/665</guid><dc:creator><![CDATA[Dimi]]></dc:creator><pubDate>Tue, 27 Mar 2018 04:58:19 GMT</pubDate></item><item><title><![CDATA[Reply to Lesson 6.1. Speaker. MP3 player on Mon, 26 Mar 2018 15:38:44 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/dimi" aria-label="Profile: dimi">@<bdi>dimi</bdi></a><br />
where do the pins connect to? GND and 25?</p>
<p dir="auto">if i wanted to connect a headphone to M5 I just do the same thing but with the headphone jack input?</p>
]]></description><link>https://community.m5stack.com/post/658</link><guid isPermaLink="true">https://community.m5stack.com/post/658</guid><dc:creator><![CDATA[m5dude]]></dc:creator><pubDate>Mon, 26 Mar 2018 15:38:44 GMT</pubDate></item><item><title><![CDATA[Reply to Lesson 6.1. Speaker. MP3 player on Mon, 26 Mar 2018 11:31:01 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/m5dude" aria-label="Profile: m5dude">@<bdi>m5dude</bdi></a> thanks! you can use <img src="https://pbs.twimg.com/media/DZNhbc_U8AEExbh.jpg:large" alt="alt text" class=" img-fluid img-markdown" /></p>
]]></description><link>https://community.m5stack.com/post/657</link><guid isPermaLink="true">https://community.m5stack.com/post/657</guid><dc:creator><![CDATA[Dimi]]></dc:creator><pubDate>Mon, 26 Mar 2018 11:31:01 GMT</pubDate></item><item><title><![CDATA[Reply to Lesson 6.1. Speaker. MP3 player on Sat, 24 Mar 2018 05:43:35 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/dimi" aria-label="Profile: Dimi">@<bdi>Dimi</bdi></a>  great stuff! you are a true wizard!</p>
<p dir="auto">question - how to add headphone jack to m5? is there an easy and elegant solution for this? perhaps with the line out stuff you pointed us to?</p>
]]></description><link>https://community.m5stack.com/post/646</link><guid isPermaLink="true">https://community.m5stack.com/post/646</guid><dc:creator><![CDATA[m5dude]]></dc:creator><pubDate>Sat, 24 Mar 2018 05:43:35 GMT</pubDate></item><item><title><![CDATA[Reply to Lesson 6.1. Speaker. MP3 player on Fri, 23 Mar 2018 20:19:01 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/dimi" aria-label="Profile: dimi">@<bdi>dimi</bdi></a> Hi Dimi,<br />
Another excellent lesson..... look forward to testing this and also testing the line out capability.</p>
]]></description><link>https://community.m5stack.com/post/641</link><guid isPermaLink="true">https://community.m5stack.com/post/641</guid><dc:creator><![CDATA[JJ]]></dc:creator><pubDate>Fri, 23 Mar 2018 20:19:01 GMT</pubDate></item></channel></rss>