├── 3d_printer_box └── makepython_audio.stl ├── ESP32-audioI2S.zip ├── bluetooth_stereo ├── bluetooth_stereo.ino └── makerfabs_pin.h ├── md_pic ├── 3.5mm.JPG ├── 3d1.png ├── 3d2.png ├── Without_plug.png ├── button_control.png ├── image-20200708115047882.png ├── image-20200708115545998.png ├── image-20200708120243416.png ├── image-20200708134131231.png ├── main.JPG ├── music_info.JPG ├── music_info2.JPG ├── oversee.png └── oversee2.png ├── music_player └── music_player.ino ├── old-src ├── esp32_i2stest │ ├── I2S.cpp │ ├── I2S.h │ └── esp32_i2stest.ino ├── esp32_mp3 │ ├── ESP32-audioI2S │ │ ├── .github │ │ │ └── stale.yml │ │ ├── LICENSE │ │ ├── README.md │ │ ├── additional_info │ │ │ └── Testfiles │ │ │ │ ├── 320k_test.mp3 │ │ │ │ ├── LightMusic.wav │ │ │ │ ├── MoonlightBay.mp3 │ │ │ │ ├── PrettyWorld.wav │ │ │ │ ├── beep.mp3 │ │ │ │ ├── click.mp3 │ │ │ │ ├── seconds-CBR.mp3 │ │ │ │ ├── seconds-VBR.mp3 │ │ │ │ ├── test.wav │ │ │ │ ├── test_8bit_mono.wav │ │ │ │ ├── test_8bit_stereo.wav │ │ │ │ └── wobble.mp3 │ │ ├── examples │ │ │ ├── ESP32-A1S │ │ │ │ ├── A1S.pdf │ │ │ │ ├── ESP32-A1S Product Specification.pdf │ │ │ │ ├── ESP32-Aduio-Kit WiFi+ bluetooth Module ESP32.jpeg │ │ │ │ └── ESP32_A1S.ino │ │ │ ├── I2Saudio.ino │ │ │ ├── M5Stack.ino │ │ │ └── Simple WiFI Radio │ │ │ │ ├── Simple_WiFi_Radio.ino │ │ │ │ ├── Simple_WiFi_Radio.jpg │ │ │ │ ├── Simple_WiFi_Radio_1.jpg │ │ │ │ ├── Simple_WiFi_Radio_2.jpg │ │ │ │ ├── Simple_WiFi_Radio_3.jpg │ │ │ │ └── Simple_WiFi_Radio_4.jpg │ │ ├── keywords.txt │ │ ├── library.properties │ │ └── src │ │ │ ├── Audio.cpp │ │ │ ├── Audio.h │ │ │ ├── aac_decoder │ │ │ ├── aac_decoder.cpp │ │ │ └── aac_decoder.h │ │ │ └── mp3_decoder │ │ │ ├── mp3_decoder.cpp │ │ │ └── mp3_decoder.h │ └── esp32_mp3.ino ├── esp32_sdtest │ └── esp32_sdtest.ino ├── esp32_ssd1306test │ └── esp32_ssd1306test.ino ├── esp32_wav_player │ ├── I2S.cpp │ ├── I2S.h │ └── esp32_wav_player.ino └── micropython_code │ ├── esp32_tts.bin │ └── workSpace │ ├── __pycache__ │ └── sdcard.cpython-38.pyc │ ├── audio_set.py │ ├── display_ssd1306_i2c.py │ ├── music.py │ ├── sdcard.py │ ├── sdread.py │ ├── sdtest.py │ ├── ssd1306.py │ ├── test.py │ ├── test2.py │ └── test3.py ├── readme-oldversion.md └── readme.md /3d_printer_box/makepython_audio.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Makerfabs/Project_MakePython_Audio_Music/3675eecd3b1562700e8ce36420fdf39be5d961e1/3d_printer_box/makepython_audio.stl -------------------------------------------------------------------------------- /ESP32-audioI2S.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Makerfabs/Project_MakePython_Audio_Music/3675eecd3b1562700e8ce36420fdf39be5d961e1/ESP32-audioI2S.zip -------------------------------------------------------------------------------- /bluetooth_stereo/bluetooth_stereo.ino: -------------------------------------------------------------------------------- 1 | #include 2 | //#include 3 | #include 4 | #include "time.h" 5 | #include "makerfabs_pin.h" 6 | #include 7 | 8 | //SSD1306 9 | #define MAKEPYTHON_ESP32_SDA 4 10 | #define MAKEPYTHON_ESP32_SCL 5 11 | #define SCREEN_WIDTH 128 // OLED display width, in pixels 12 | #define SCREEN_HEIGHT 64 // OLED display height, in pixels 13 | 14 | #define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin) 15 | 16 | Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); 17 | 18 | //Button 19 | const int Pin_vol_up = 39; 20 | const int Pin_vol_down = 36; 21 | const int Pin_mute = 35; 22 | 23 | const int Pin_previous = 15; 24 | const int Pin_pause = 33; 25 | const int Pin_next = 2; 26 | 27 | //WIFI 28 | const char *ssid = "Tenda_195"; 29 | const char *password = "xbw941024"; 30 | 31 | //NTP time 32 | //const char* ntpServer = "pool.ntp.org"; 33 | const char *ntpServer = "120.25.108.11"; 34 | const long gmtOffset_sec = 8 * 60 * 60; //China+8 35 | const int daylightOffset_sec = 0; 36 | 37 | /* 38 | String clock_time = "20:14:0"; 39 | String clock_time2 = "20:16:0"; 40 | */ 41 | 42 | String clock_time = "07:45:0"; 43 | String clock_time2 = "08:00:0"; 44 | 45 | 46 | struct tm timeinfo; 47 | 48 | // Sets the name of the audio device 49 | btAudio audio = btAudio("ESP_Speaker"); 50 | 51 | void setup() 52 | { 53 | 54 | //IO mode init 55 | pinMode(Pin_vol_up, INPUT_PULLUP); 56 | pinMode(Pin_vol_down, INPUT_PULLUP); 57 | pinMode(Pin_mute, INPUT_PULLUP); 58 | pinMode(Pin_previous, INPUT_PULLUP); 59 | pinMode(Pin_pause, INPUT_PULLUP); 60 | pinMode(Pin_next, INPUT_PULLUP); 61 | 62 | Serial.begin(115200); 63 | 64 | Wire.begin(MAKEPYTHON_ESP32_SDA, MAKEPYTHON_ESP32_SCL); 65 | // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally 66 | if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) 67 | { // Address 0x3D for 128x64 68 | Serial.println(F("SSD1306 allocation failed")); 69 | for (;;) 70 | ; // Don't proceed, loop forever 71 | } 72 | 73 | // Show initial display buffer contents on the screen -- 74 | // the library initializes this with an Adafruit splash screen. 75 | display.display(); 76 | display.setRotation(2); 77 | logoshow(); 78 | 79 | //connect to WiFi 80 | Serial.printf("Connecting to %s ", ssid); 81 | WiFi.begin(ssid, password); 82 | while (WiFi.status() != WL_CONNECTED) 83 | { 84 | delay(500); 85 | Serial.print("."); 86 | } 87 | Serial.println(" CONNECTED"); 88 | lcd_text("Wifi OK"); 89 | 90 | //init and get the time 91 | configTime(gmtOffset_sec, daylightOffset_sec, ntpServer); 92 | Serial.println("Alread get npt time."); 93 | printLocalTime(); 94 | lcd_text("NPT FLESH"); 95 | 96 | //disconnect WiFi as it's no longer needed 97 | WiFi.disconnect(true); 98 | WiFi.mode(WIFI_OFF); 99 | 100 | // streams audio data to the ESP32 101 | audio.begin(); 102 | 103 | // outputs the received data to an I2S DAC https://www.adafruit.com/product/3678 104 | int bck = MP_AUDIO_I2S_BCLK; 105 | int ws = MP_AUDIO_I2S_LRC; 106 | int dout = MP_AUDIO_I2S_DOUT; 107 | audio.I2S(bck, dout, ws); 108 | } 109 | 110 | unsigned long button_time = 0; 111 | unsigned long run_time = 0; 112 | uint alarm_flag = 0; 113 | int16_t fy[2] = {10000, 60000}; 114 | size_t i2s_bytes_write = 0; 115 | 116 | void loop() 117 | { 118 | if (millis() - button_time > 1200) 119 | { 120 | printLocalTime(); 121 | if (alarm_flag == 0) 122 | { 123 | if (showtime() != 0) 124 | { 125 | run_time = millis(); 126 | alarm_flag = 1; 127 | display.setCursor(0, 24); // Start at top-left corner 128 | display.println("ALARM!!!!!"); 129 | display.display(); 130 | delay(1000); 131 | button_time = millis(); 132 | } 133 | } 134 | } 135 | 136 | while (alarm_flag) 137 | { 138 | for (int i = 0; i < 100; i++) 139 | { 140 | i2s_write(I2S_NUM_0, fy, 1, &i2s_bytes_write, 100); 141 | fy[0]++; 142 | fy[1]++; 143 | } 144 | Serial.println("alarm"); 145 | //Button logic 146 | if (digitalRead(Pin_mute) == 0) 147 | { 148 | Serial.println("Pin_mute"); 149 | alarm_flag = 0; 150 | button_time = millis(); 151 | } 152 | if((millis() - run_time) > 60000) 153 | { 154 | Serial.println("Alarm over"); 155 | alarm_flag = 0; 156 | } 157 | } 158 | 159 | if (digitalRead(Pin_pause) == 0) 160 | { 161 | showalarm(); 162 | } 163 | } 164 | 165 | void logoshow() 166 | { 167 | display.clearDisplay(); 168 | 169 | display.setTextSize(2); // Normal 1:1 pixel scale 170 | display.setTextColor(SSD1306_WHITE); // Draw white text 171 | display.setCursor(0, 0); // Start at top-left corner 172 | display.println("MakePython"); 173 | display.setCursor(0, 20); // Start at top-left corner 174 | display.println("WAKEMASTER"); 175 | display.display(); 176 | delay(2000); 177 | } 178 | 179 | void lcd_text(String text) 180 | { 181 | display.clearDisplay(); 182 | display.setTextSize(2); 183 | display.setTextColor(SSD1306_WHITE); // Draw white text 184 | display.setCursor(0, 0); // Start at top-left corner 185 | display.println(text); 186 | display.display(); 187 | delay(500); 188 | } 189 | 190 | void showalarm() 191 | { 192 | display.clearDisplay(); 193 | display.setTextSize(3); 194 | display.setCursor(0, 0); // Start at top-left corner 195 | display.println(clock_time); 196 | display.println(clock_time2); 197 | display.display(); 198 | delay(5000); 199 | } 200 | 201 | int showtime() 202 | { 203 | int hour = timeinfo.tm_hour; 204 | int min = timeinfo.tm_min; 205 | int sec = timeinfo.tm_sec; 206 | char time_str[10]; 207 | sprintf(time_str, "%02d:%02d:%02d", hour, min, sec); 208 | display.clearDisplay(); 209 | display.setTextSize(4); 210 | display.setCursor(0, 0); // Start at top-left corner 211 | display.println(time_str); 212 | display.display(); 213 | String temp = (String)time_str; 214 | if (temp.startsWith(clock_time)) 215 | { 216 | return 1; 217 | } 218 | if (temp.startsWith(clock_time2)) 219 | { 220 | return 2; 221 | } 222 | return 0; 223 | } 224 | 225 | void printLocalTime() 226 | { 227 | 228 | if (!getLocalTime(&timeinfo)) 229 | { 230 | Serial.println("Failed to obtain time"); 231 | display.clearDisplay(); 232 | display.setTextSize(4); 233 | display.setCursor(0, 0); // Start at top-left corner 234 | display.println("PLEASE RESTART"); 235 | display.display(); 236 | while(1); 237 | return; 238 | } 239 | Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S"); 240 | } 241 | -------------------------------------------------------------------------------- /bluetooth_stereo/makerfabs_pin.h: -------------------------------------------------------------------------------- 1 | /* 2 | ------------------------------------------------- 3 | titile : Makerfabs IO define 4 | author : Vincent 5 | create : 2020/9/4 6 | version : 1.0 7 | update : 2020/9/8 8 | 9 | Note: 10 | 11 | 1. 12 | For easy use ESP32 GPIO,define SPI, I2C, and LCD, SDcard pins. 13 | And define some parameters, such as screen size. 14 | 15 | 2. 16 | Sigillum: 17 | MP = MakePython 18 | MP_ESP32 = MakePython ESP32 SSD1306 19 | MP_ESP32_COLOR = MakePython ESP32 Color LCD (ST7789) 20 | 21 | TSC = Touch Screen Camera 22 | ESP32_TSC_9488 = ESP32 Touch Screen Camera With ILI9488 23 | 24 | 3. 25 | //#define ESP32_COLOR_7789 OK 26 | "Ok" means tested and ready to use 27 | Don't use "ERR" or "TEST" 28 | 29 | 4. 30 | For the motherboard combination expansion board. 31 | This is to be determined and may be modified. 32 | A more prudent approach is to copy the pin value directly. 33 | 34 | ------------------------------------------------- 35 | Support List: 36 | 37 | (1)MakePython: 38 | MakePython ESP32 COLOR LCD 39 | MakePython ESP32 SSD1306 40 | 41 | (2)Touch Screen Camera: 42 | ESP32 Touch Screen Camera With 9488 43 | 44 | ------------------------------------------------- 45 | */ 46 | 47 | //BOARD 48 | 49 | #define MP_ESP32 OK 50 | //#define MP_ESP32_COLOR OK 51 | //#define ESP32_TSC_9488 OK 52 | //#define ESP32_ILI9341 ERR don't use 53 | 54 | //SHIELD 55 | #define MP_AUDIO OK 56 | 57 | /* 58 | update : 2020/9/8 59 | name : MakePython ESP32 SSD1306 60 | sigillum: MP_ESP32_COLOR 61 | wiki : https://www.makerfabs.com/wiki/index.php?title=MakePython_ESP32 62 | module : 63 | (1) 1.3inch OLED SSD1306 64 | 65 | */ 66 | #ifdef MP_ESP32 67 | 68 | #define MP_ESP32_FLASH_BUTTON 0 69 | 70 | //I2C 71 | #define MP_ESP32_I2C_SDA 4 72 | #define MP_ESP32_I2C_SCL 5 73 | 74 | //HSPI 75 | #define MP_ESP32_HSPI_MOSI 13 76 | #define MP_ESP32_HSPI_MISO 12 77 | #define MP_ESP32_HSPI_SCK 14 78 | #define MP_ESP32_HSPI_CS 15 79 | 80 | //VSPI 81 | #define MP_ESP32_VSPI_MOSI 23 82 | #define MP_ESP32_VSPI_MISO 19 83 | #define MP_ESP32_VSPI_SCK 18 84 | #define MP_ESP32_VSPI_CS 5 85 | 86 | //SSD1306 87 | #define MP_ESP32_SSD1306_I2C_ADDR 0x3C 88 | #define MP_ESP32_SSD1306_WIDTH 128 // OLED display width, in pixels 89 | #define MP_ESP32_SSD1306_HEIGHT 64 // OLED display height, in pixels 90 | #define MP_ESP32_SSD1306_RST 4 91 | 92 | #endif 93 | 94 | /* 95 | update : 2020/9/11 96 | name : MakePython ESP32 COLOR LCD 97 | sigillum: MP_ESP32_COLOR 98 | wiki : https://www.makerfabs.com/wiki/index.php?title=MakePython_ESP32_Color_LCD 99 | module : 100 | (1) 1.3inch TFT ST7789 driver 101 | 102 | */ 103 | #ifdef MP_ESP32_COLOR 104 | 105 | //I2C 106 | #define MP_ESP32_COLOR_I2C_SDA 4 107 | #define MP_ESP32_COLOR_I2C_SCL 5 108 | 109 | //HSPI 110 | #define MP_ESP32_COLOR_HSPI_MOSI 13 111 | #define MP_ESP32_COLOR_HSPI_MISO 12 112 | #define MP_ESP32_COLOR_HSPI_SCK 14 113 | #define MP_ESP32_COLOR_HSPI_CS 15 114 | 115 | //VSPI 116 | #define MP_ESP32_COLOR_VSPI_MOSI 23 117 | #define MP_ESP32_COLOR_VSPI_MISO 19 118 | #define MP_ESP32_COLOR_VSPI_SCK 18 119 | #define MP_ESP32_COLOR_VSPI_CS 5 120 | 121 | //ST7789 122 | #define MP_ESP32_COLOR_LCD_MOSI MP_ESP32_COLOR_HSPI_MOSI 123 | #define MP_ESP32_COLOR_LCD_MISO MP_ESP32_COLOR_HSPI_MISO 124 | #define MP_ESP32_COLOR_LCD_SCK MP_ESP32_COLOR_HSPI_SCK 125 | 126 | #define MP_ESP32_COLOR_LCD_CS 15 127 | 128 | #define MP_ESP32_COLOR_LCD_RST 21 129 | #define MP_ESP32_COLOR_LCD_DC 22 130 | #define MP_ESP32_COLOR_LCD_BL -1 //5 131 | 132 | #define MP_ESP32_COLOR_LCD_WIDTH 240 133 | #define MP_ESP32_COLOR_LCD_HEIGHT 240 134 | #define MP_ESP32_COLOR_LCD_SPI_HOST HSPI_HOST 135 | 136 | #endif 137 | 138 | /* 139 | update : 2020/9/4 140 | name : ESP32 Touch Screen Camera With ILI9488 141 | sigillum: ESP32_TSC_9488 142 | wiki : 143 | module : 144 | (1) 3.5inch TFT ILI9488 driver 145 | (2) SDcard Reader 146 | (3) I2C Touch Screen(NS2009 or Ft6236) 147 | (4) OV2640 Camera 148 | */ 149 | 150 | #ifdef ESP32_TSC_9488 151 | 152 | //I2C 153 | #define ESP32_TSC_9488_I2C_SDA 26 154 | #define ESP32_TSC_9488_I2C_SCL 27 155 | 156 | //SPI 157 | #define ESP32_TSC_9488_HSPI_MOSI 13 158 | #define ESP32_TSC_9488_HSPI_MISO 12 159 | #define ESP32_TSC_9488_HSPI_SCK 14 160 | #define ESP32_TSC_9488_HSPI_CS 15 161 | 162 | //ILI9488 163 | #define ESP32_TSC_9488_LCD_MOSI ESP32_TSC_9488_HSPI_MOSI 164 | #define ESP32_TSC_9488_LCD_MISO ESP32_TSC_9488_HSPI_MISO 165 | #define ESP32_TSC_9488_LCD_SCK ESP32_TSC_9488_HSPI_SCK 166 | 167 | #define ESP32_TSC_9488_LCD_CS 15 168 | 169 | #define ESP32_TSC_9488_LCD_RST 26 170 | #define ESP32_TSC_9488_LCD_DC 33 171 | #define ESP32_TSC_9488_LCD_BL -1 172 | 173 | #define ESP32_TSC_9488_LCD_WIDTH 320 174 | #define ESP32_TSC_9488_LCD_HEIGHT 480 175 | #define ESP32_TSC_9488_LCD_SPI_HOST HSPI_HOST 176 | 177 | //SDcard 178 | #define ESP32_TSC_9488_SD_MOSI ESP32_TSC_9488_HSPI_MOSI 179 | #define ESP32_TSC_9488_SD_MISO ESP32_TSC_9488_HSPI_MISO 180 | #define ESP32_TSC_9488_SD_SCK ESP32_TSC_9488_HSPI_SCK 181 | 182 | #define ESP32_TSC_9488_SD_CS 4 183 | 184 | #endif 185 | 186 | /* 187 | name : ESP32 Touch Screen Camera With ILI9341 188 | Not ready 189 | */ 190 | 191 | #ifdef ESP32_ILI9341 192 | 193 | #define LCD_MOSI 13 194 | #define LCD_MISO 12 195 | #define LCD_SCK 14 196 | #define LCD_CS 18 197 | #define LCD_RST 21 198 | #define LCD_DC 22 199 | #define LCD_BL 19 //5 200 | 201 | #define LCD_WIDTH 240 202 | #define LCD_HEIGHT 240 203 | #define LCD_SPI_HOST VSPI_HOST 204 | 205 | #endif 206 | 207 | /* 208 | update : 2020/9/11 209 | name : MakePython ESP32 Audio 210 | sigillum: MP_AUDIO 211 | wiki : https://www.makerfabs.com/wiki/index.php?title=MakePython_Audio 212 | module : 213 | (1) audio jack(3.5mm) 214 | (2) SD Card 215 | (3) NXP Low power Audio DAC: uDA1334 216 | 217 | */ 218 | 219 | #ifdef MP_AUDIO 220 | 221 | //SD Card 222 | #define MP_AUDIO_SD_CS 22 223 | 224 | #if defined MP_ESP32 225 | #define MP_AUDIO_SPI_MOSI MP_ESP32_VSPI_MOSI 226 | #define MP_AUDIO_SPI_MISO MP_ESP32_VSPI_MISO 227 | #define MP_AUDIO_SPI_SCK MP_ESP32_VSPI_SCK 228 | 229 | #elif defined MP_ESP32_COLOR 230 | #define MP_AUDIO_SPI_MOSI MP_ESP32_COLOR_VSPI_MOSI 231 | #define MP_AUDIO_SPI_MISO MP_ESP32_COLOR_VSPI_MISO 232 | #define MP_AUDIO_SPI_SCK MP_ESP32_COLOR_VSPI_SCK 233 | 234 | #else 235 | #define MP_AUDIO_SPI_MOSI 23 236 | #define MP_AUDIO_SPI_MISO 19 237 | #define MP_AUDIO_SPI_SCK 18 238 | 239 | #endif 240 | 241 | //Digital I/O used //Makerfabs Audio V2.0 242 | #define MP_AUDIO_I2S_DOUT 27 243 | #define MP_AUDIO_I2S_BCLK 26 244 | #define MP_AUDIO_I2S_LRC 25 245 | 246 | //Button 247 | #define MP_AUDIO_Pin_vol_up 39 248 | #define MP_AUDIO_Pin_vol_down 36 249 | #define MP_AUDIO_Pin_mute 35 250 | #define MP_AUDIO_Pin_previous 15 251 | #define MP_AUDIO_Pin_pause 33 252 | #define MP_AUDIO_Pin_next 2 253 | 254 | #endif -------------------------------------------------------------------------------- /md_pic/3.5mm.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Makerfabs/Project_MakePython_Audio_Music/3675eecd3b1562700e8ce36420fdf39be5d961e1/md_pic/3.5mm.JPG -------------------------------------------------------------------------------- /md_pic/3d1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Makerfabs/Project_MakePython_Audio_Music/3675eecd3b1562700e8ce36420fdf39be5d961e1/md_pic/3d1.png -------------------------------------------------------------------------------- /md_pic/3d2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Makerfabs/Project_MakePython_Audio_Music/3675eecd3b1562700e8ce36420fdf39be5d961e1/md_pic/3d2.png -------------------------------------------------------------------------------- /md_pic/Without_plug.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Makerfabs/Project_MakePython_Audio_Music/3675eecd3b1562700e8ce36420fdf39be5d961e1/md_pic/Without_plug.png -------------------------------------------------------------------------------- /md_pic/button_control.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Makerfabs/Project_MakePython_Audio_Music/3675eecd3b1562700e8ce36420fdf39be5d961e1/md_pic/button_control.png -------------------------------------------------------------------------------- /md_pic/image-20200708115047882.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Makerfabs/Project_MakePython_Audio_Music/3675eecd3b1562700e8ce36420fdf39be5d961e1/md_pic/image-20200708115047882.png -------------------------------------------------------------------------------- /md_pic/image-20200708115545998.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Makerfabs/Project_MakePython_Audio_Music/3675eecd3b1562700e8ce36420fdf39be5d961e1/md_pic/image-20200708115545998.png -------------------------------------------------------------------------------- /md_pic/image-20200708120243416.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Makerfabs/Project_MakePython_Audio_Music/3675eecd3b1562700e8ce36420fdf39be5d961e1/md_pic/image-20200708120243416.png -------------------------------------------------------------------------------- /md_pic/image-20200708134131231.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Makerfabs/Project_MakePython_Audio_Music/3675eecd3b1562700e8ce36420fdf39be5d961e1/md_pic/image-20200708134131231.png -------------------------------------------------------------------------------- /md_pic/main.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Makerfabs/Project_MakePython_Audio_Music/3675eecd3b1562700e8ce36420fdf39be5d961e1/md_pic/main.JPG -------------------------------------------------------------------------------- /md_pic/music_info.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Makerfabs/Project_MakePython_Audio_Music/3675eecd3b1562700e8ce36420fdf39be5d961e1/md_pic/music_info.JPG -------------------------------------------------------------------------------- /md_pic/music_info2.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Makerfabs/Project_MakePython_Audio_Music/3675eecd3b1562700e8ce36420fdf39be5d961e1/md_pic/music_info2.JPG -------------------------------------------------------------------------------- /md_pic/oversee.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Makerfabs/Project_MakePython_Audio_Music/3675eecd3b1562700e8ce36420fdf39be5d961e1/md_pic/oversee.png -------------------------------------------------------------------------------- /md_pic/oversee2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Makerfabs/Project_MakePython_Audio_Music/3675eecd3b1562700e8ce36420fdf39be5d961e1/md_pic/oversee2.png -------------------------------------------------------------------------------- /music_player/music_player.ino: -------------------------------------------------------------------------------- 1 | #include "Arduino.h" 2 | //#include "WiFiMulti.h" 3 | #include "Audio.h" 4 | #include "SPI.h" 5 | #include "SD.h" 6 | #include "FS.h" 7 | #include 8 | #include 9 | 10 | //SD Card 11 | #define SD_CS 22 12 | #define SPI_MOSI 23 13 | #define SPI_MISO 19 14 | #define SPI_SCK 18 15 | 16 | //Digital I/O used //Makerfabs Audio V2.0 17 | #define I2S_DOUT 27 18 | #define I2S_BCLK 26 19 | #define I2S_LRC 25 20 | 21 | //SSD1306 22 | #define MAKEPYTHON_ESP32_SDA 4 23 | #define MAKEPYTHON_ESP32_SCL 5 24 | #define SCREEN_WIDTH 128 // OLED display width, in pixels 25 | #define SCREEN_HEIGHT 64 // OLED display height, in pixels 26 | #define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin) 27 | 28 | Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); 29 | 30 | //Button 31 | const int Pin_vol_up = 39; 32 | const int Pin_vol_down = 36; 33 | const int Pin_mute = 35; 34 | 35 | const int Pin_previous = 15; 36 | const int Pin_pause = 33; 37 | const int Pin_next = 2; 38 | 39 | Audio audio; 40 | 41 | /* 42 | WiFiMulti wifiMulti; 43 | String ssid = "Makerfabs"; 44 | String password = "20160704"; 45 | */ 46 | 47 | struct Music_info 48 | { 49 | String name; 50 | int length; 51 | int runtime; 52 | int volume; 53 | int status; 54 | int mute_volume; 55 | } music_info = {"", 0, 0, 0, 0, 0}; 56 | 57 | String file_list[20]; 58 | int file_num = 0; 59 | int file_index = 0; 60 | 61 | void setup() 62 | { 63 | //IO mode init 64 | pinMode(Pin_vol_up, INPUT_PULLUP); 65 | pinMode(Pin_vol_down, INPUT_PULLUP); 66 | pinMode(Pin_mute, INPUT_PULLUP); 67 | pinMode(Pin_previous, INPUT_PULLUP); 68 | pinMode(Pin_pause, INPUT_PULLUP); 69 | pinMode(Pin_next, INPUT_PULLUP); 70 | 71 | //Serial 72 | Serial.begin(115200); 73 | 74 | //LCD 75 | Wire.begin(MAKEPYTHON_ESP32_SDA, MAKEPYTHON_ESP32_SCL); 76 | // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally 77 | if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) 78 | { // Address 0x3C for 128x32 79 | Serial.println(F("SSD1306 allocation failed")); 80 | for (;;) 81 | ; // Don't proceed, loop forever 82 | } 83 | display.clearDisplay(); 84 | logoshow(); 85 | 86 | //SD(SPI) 87 | pinMode(SD_CS, OUTPUT); 88 | digitalWrite(SD_CS, HIGH); 89 | SPI.begin(SPI_SCK, SPI_MISO, SPI_MOSI); 90 | SPI.setFrequency(1000000); 91 | if (!SD.begin(SD_CS, SPI)) 92 | { 93 | Serial.println("Card Mount Failed"); 94 | lcd_text("SD ERR"); 95 | while (1) 96 | ; 97 | } 98 | else 99 | { 100 | lcd_text("SD OK"); 101 | } 102 | 103 | //Read SD 104 | file_num = get_music_list(SD, "/", 0, file_list); 105 | Serial.print("Music file count:"); 106 | Serial.println(file_num); 107 | Serial.println("All music:"); 108 | for (int i = 0; i < file_num; i++) 109 | { 110 | Serial.println(file_list[i]); 111 | } 112 | 113 | //WiFi 114 | /* 115 | WiFi.mode(WIFI_STA); 116 | wifiMulti.addAP(ssid.c_str(), password.c_str()); 117 | wifiMulti.run(); 118 | if (WiFi.status() != WL_CONNECTED) 119 | { 120 | WiFi.disconnect(true); 121 | wifiMulti.run(); 122 | } 123 | */ 124 | 125 | //Audio(I2S) 126 | audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT); 127 | audio.setVolume(21); // 0...21 128 | 129 | //audio.connecttoFS(SD, "/MoonlightBay.mp3"); //ChildhoodMemory.mp3 //MoonRiver.mp3 //320k_test.mp3 130 | //file_list[0] = "MoonlightBay.mp3"; 131 | open_new_song(file_list[file_index]); 132 | print_song_time(); 133 | } 134 | 135 | uint run_time = 0; 136 | uint button_time = 0; 137 | 138 | void loop() 139 | { 140 | audio.loop(); 141 | if (millis() - run_time > 1000) 142 | { 143 | run_time = millis(); 144 | print_song_time(); 145 | display_music(); 146 | } 147 | 148 | if (millis() - button_time > 300) 149 | { 150 | //Button logic 151 | if (digitalRead(Pin_next) == 0) 152 | { 153 | Serial.println("Pin_next"); 154 | if (file_index < file_num - 1) 155 | file_index++; 156 | else 157 | file_index = 0; 158 | open_new_song(file_list[file_index]); 159 | print_song_time(); 160 | button_time = millis(); 161 | } 162 | if (digitalRead(Pin_previous) == 0) 163 | { 164 | Serial.println("Pin_previous"); 165 | if (file_index > 0) 166 | file_index--; 167 | else 168 | file_index = file_num - 1; 169 | open_new_song(file_list[file_index]); 170 | print_song_time(); 171 | button_time = millis(); 172 | } 173 | if (digitalRead(Pin_vol_up) == 0) 174 | { 175 | Serial.println("Pin_vol_up"); 176 | if (music_info.volume < 21) 177 | music_info.volume++; 178 | audio.setVolume(music_info.volume); 179 | button_time = millis(); 180 | } 181 | if (digitalRead(Pin_vol_down) == 0) 182 | { 183 | Serial.println("Pin_vol_down"); 184 | if (music_info.volume > 0) 185 | music_info.volume--; 186 | audio.setVolume(music_info.volume); 187 | button_time = millis(); 188 | } 189 | if (digitalRead(Pin_mute) == 0) 190 | { 191 | Serial.println("Pin_mute"); 192 | if (music_info.volume != 0) 193 | { 194 | music_info.mute_volume = music_info.volume; 195 | music_info.volume = 0; 196 | } 197 | else 198 | { 199 | music_info.volume = music_info.mute_volume; 200 | } 201 | audio.setVolume(music_info.volume); 202 | button_time = millis(); 203 | } 204 | if (digitalRead(Pin_pause) == 0) 205 | { 206 | Serial.println("Pin_pause"); 207 | audio.pauseResume(); 208 | button_time = millis(); 209 | } 210 | } 211 | 212 | //串口控制切歌,音量 213 | if (Serial.available()) 214 | { 215 | String r = Serial.readString(); 216 | r.trim(); 217 | if (r.length() > 5) 218 | { 219 | audio.stopSong(); 220 | open_new_song(file_list[0]); 221 | print_song_info(); 222 | } 223 | else 224 | { 225 | audio.setVolume(r.toInt()); 226 | } 227 | } 228 | } 229 | 230 | void open_new_song(String filename) 231 | { 232 | //去掉文件名的根目录"/"和文件后缀".mp3",".wav" 233 | music_info.name = filename.substring(1, filename.indexOf(".")); 234 | audio.connecttoFS(SD, filename); 235 | music_info.runtime = audio.getAudioCurrentTime(); 236 | music_info.length = audio.getAudioFileDuration(); 237 | music_info.volume = audio.getVolume(); 238 | music_info.status = 1; 239 | Serial.println("**********start a new sound************"); 240 | } 241 | 242 | void display_music() 243 | { 244 | int line_step = 24; 245 | int line = 0; 246 | char buff[20]; 247 | ; 248 | sprintf(buff, "%d:%d", music_info.runtime, music_info.length); 249 | 250 | display.clearDisplay(); 251 | 252 | display.setTextSize(2); // Normal 1:1 pixel scale 253 | display.setTextColor(SSD1306_WHITE); // Draw white text 254 | 255 | display.setCursor(0, line); // Start at top-left corner 256 | display.println(music_info.name); 257 | line += line_step; 258 | 259 | display.setCursor(0, line); 260 | display.println(buff); 261 | line += line_step; 262 | 263 | sprintf(buff, "V:%d",music_info.volume); 264 | 265 | display.setCursor(0, line); 266 | display.println(buff); 267 | line += line_step; 268 | 269 | display.setCursor(0, line); 270 | display.println(music_info.status); 271 | line += line_step; 272 | 273 | display.display(); 274 | } 275 | 276 | void logoshow(void) 277 | { 278 | display.clearDisplay(); 279 | 280 | display.setTextSize(2); // Normal 1:1 pixel scale 281 | display.setTextColor(SSD1306_WHITE); // Draw white text 282 | display.setCursor(0, 0); // Start at top-left corner 283 | display.println(F("MakePython")); 284 | display.setCursor(0, 20); // Start at top-left corner 285 | display.println(F("MUSIC")); 286 | display.setCursor(0, 40); // Start at top-left corner 287 | display.println(F("PLAYER V2")); 288 | display.display(); 289 | delay(2000); 290 | } 291 | 292 | void lcd_text(String text) 293 | { 294 | display.clearDisplay(); 295 | 296 | display.setTextSize(2); // Normal 1:1 pixel scale 297 | display.setTextColor(SSD1306_WHITE); // Draw white text 298 | display.setCursor(0, 0); // Start at top-left corner 299 | display.println(text); 300 | display.display(); 301 | delay(500); 302 | } 303 | 304 | void print_song_info() 305 | { 306 | Serial.println("***********************************"); 307 | Serial.println(audio.getFileSize()); 308 | Serial.println(audio.getFilePos()); 309 | Serial.println(audio.getSampleRate()); 310 | Serial.println(audio.getBitsPerSample()); 311 | Serial.println(audio.getChannels()); 312 | Serial.println(audio.getVolume()); 313 | Serial.println("***********************************"); 314 | } 315 | 316 | //刷新歌曲时间 317 | void print_song_time() 318 | { 319 | //Serial.println(audio.getAudioCurrentTime()); 320 | //Serial.println(audio.getAudioFileDuration()); 321 | music_info.runtime = audio.getAudioCurrentTime(); 322 | music_info.length = audio.getAudioFileDuration(); 323 | music_info.volume = audio.getVolume(); 324 | } 325 | 326 | int get_music_list(fs::FS &fs, const char *dirname, uint8_t levels, String wavlist[30]) 327 | { 328 | Serial.printf("Listing directory: %s\n", dirname); 329 | int i = 0; 330 | 331 | File root = fs.open(dirname); 332 | if (!root) 333 | { 334 | Serial.println("Failed to open directory"); 335 | return i; 336 | } 337 | if (!root.isDirectory()) 338 | { 339 | Serial.println("Not a directory"); 340 | return i; 341 | } 342 | 343 | File file = root.openNextFile(); 344 | while (file) 345 | { 346 | if (file.isDirectory()) 347 | { 348 | } 349 | else 350 | { 351 | String temp = file.name(); 352 | if (temp.endsWith(".wav")) 353 | { 354 | wavlist[i] = temp; 355 | i++; 356 | } 357 | else if (temp.endsWith(".mp3")) 358 | { 359 | wavlist[i] = temp; 360 | i++; 361 | } 362 | } 363 | file = root.openNextFile(); 364 | } 365 | return i; 366 | } 367 | 368 | //********************************************** 369 | // optional 370 | void audio_info(const char *info) 371 | { 372 | Serial.print("info "); 373 | Serial.println(info); 374 | } 375 | void audio_id3data(const char *info) 376 | { //id3 metadata 377 | Serial.print("id3data "); 378 | Serial.println(info); 379 | } 380 | 381 | //歌曲结束逻辑 382 | void audio_eof_mp3(const char *info) 383 | { //end of file 384 | Serial.print("eof_mp3 "); 385 | Serial.println(info); 386 | file_index++; 387 | if (file_index >= file_num) 388 | { 389 | file_index = 0; 390 | } 391 | open_new_song(file_list[file_index]); 392 | } 393 | void audio_showstation(const char *info) 394 | { 395 | Serial.print("station "); 396 | Serial.println(info); 397 | } 398 | void audio_showstreaminfo(const char *info) 399 | { 400 | Serial.print("streaminfo "); 401 | Serial.println(info); 402 | } 403 | void audio_showstreamtitle(const char *info) 404 | { 405 | Serial.print("streamtitle "); 406 | Serial.println(info); 407 | } 408 | void audio_bitrate(const char *info) 409 | { 410 | Serial.print("bitrate "); 411 | Serial.println(info); 412 | } 413 | void audio_commercial(const char *info) 414 | { //duration in sec 415 | Serial.print("commercial "); 416 | Serial.println(info); 417 | } 418 | void audio_icyurl(const char *info) 419 | { //homepage 420 | Serial.print("icyurl "); 421 | Serial.println(info); 422 | } 423 | void audio_lasthost(const char *info) 424 | { //stream URL played 425 | Serial.print("lasthost "); 426 | Serial.println(info); 427 | } 428 | void audio_eof_speech(const char *info) 429 | { 430 | Serial.print("eof_speech "); 431 | Serial.println(info); 432 | } -------------------------------------------------------------------------------- /old-src/esp32_i2stest/I2S.cpp: -------------------------------------------------------------------------------- 1 | #include "I2S.h" 2 | 3 | void I2S_Init() { 4 | i2s_config_t i2s_config = { 5 | .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX), 6 | .sample_rate = SAMPLE_RATE, 7 | .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, 8 | .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //2-channels 9 | .communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB), 10 | .intr_alloc_flags = 0, 11 | .dma_buf_count = 16, 12 | .dma_buf_len = 60 13 | }; 14 | 15 | i2s_pin_config_t pin_config = { 16 | .bck_io_num = PIN_I2S_BCLK, 17 | .ws_io_num = PIN_I2S_LRC, 18 | .data_out_num = PIN_I2S_DOUT, 19 | .data_in_num = -1 //Not used 20 | }; 21 | i2s_driver_install((i2s_port_t)0, &i2s_config, 0, NULL); 22 | i2s_set_pin((i2s_port_t)0, &pin_config); 23 | i2s_set_clk((i2s_port_t)0, SAMPLE_RATE, (i2s_bits_per_sample_t)16, (i2s_channel_t)2); 24 | } 25 | 26 | void I2S_Write(char* data, int numData) { 27 | i2s_write_bytes((i2s_port_t)0, (const char *)data, numData, portMAX_DELAY); 28 | } 29 | 30 | -------------------------------------------------------------------------------- /old-src/esp32_i2stest/I2S.h: -------------------------------------------------------------------------------- 1 | #include "freertos/FreeRTOS.h" 2 | #include "freertos/task.h" 3 | #include "driver/i2s.h" 4 | #include "esp_system.h" 5 | #define SAMPLE_RATE (44100) 6 | #define PIN_I2S_BCLK 26 7 | #define PIN_I2S_LRC 25 8 | #define PIN_I2S_DOUT 27 9 | 10 | // 44100Hz, 16bit, stereo 11 | void I2S_Init(); 12 | void I2S_Write(char* data, int numData); 13 | -------------------------------------------------------------------------------- /old-src/esp32_i2stest/esp32_i2stest.ino: -------------------------------------------------------------------------------- 1 | #include "I2S.h" 2 | #include 3 | #include 4 | 5 | const int offset = 0x2C; 6 | char data[800]; 7 | long i = 0; 8 | 9 | void setup() 10 | { 11 | Serial.begin(115200); 12 | SPI.begin(18, 19, 23, 5); 13 | if (!SD.begin(22, SPI)) 14 | { 15 | Serial.println("Card Mount Failed"); 16 | return; 17 | } 18 | 19 | File file = SD.open("/sound.wav"); // 44100Hz, 16bit, linear PCM 20 | Serial.println("OPEN FILE"); 21 | 22 | file.seek(22); 23 | int ch = file.read(); 24 | file.seek(offset); 25 | I2S_Init(); 26 | Serial.println("I2S"); 27 | 28 | while (file.readBytes(data, sizeof(data))) 29 | { 30 | I2S_Write(data, sizeof(data)); 31 | } 32 | file.close(); 33 | for (int i = 0; i < sizeof(data); ++i) 34 | data[i] = 0; // to prevent buzzing 35 | for (int i = 0; i < 5; ++i) 36 | I2S_Write(data, sizeof(data)); 37 | 38 | Serial.println("over"); 39 | } 40 | 41 | void loop() 42 | { 43 | } 44 | -------------------------------------------------------------------------------- /old-src/esp32_mp3/ESP32-audioI2S/.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 60 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 7 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - pinned 8 | - security 9 | # Label to use when marking an issue as stale 10 | staleLabel: wontfix 11 | # Comment to post when marking an issue as stale. Set to `false` to disable 12 | markComment: > 13 | This issue has been automatically marked as stale because it has not had 14 | recent activity. It will be closed if no further activity occurs. Thank you 15 | for your contributions. 16 | # Comment to post when closing a stale issue. Set to `false` to disable 17 | closeComment: false 18 | -------------------------------------------------------------------------------- /old-src/esp32_mp3/ESP32-audioI2S/README.md: -------------------------------------------------------------------------------- 1 | # ESP32-audioI2S 2 | Plays mp3 and wav files from SD card via I2S with external hardware. 3 | HELIX-mp3 and -aac decoder is included. 4 | Works with MAX98357A (3 Watt amplifier with DAC), connected three lines (DOUT, BLCK, LRC) to I2S. 5 | For stereo are two MAX98357A necessary. AudioI2S works with UDA1334A (Adafruit I2S Stereo Decoder Breakout Board) and PCM1502A. 6 | Other HW may work but not tested. Plays also icy-streams and GoogleTTS. Can be compiled with Arduino IDE. 7 | 8 | ```` c++ 9 | #include "Arduino.h" 10 | #include "WiFi.h" 11 | #include "Audio.h" 12 | #include "SD.h" 13 | #include "FS.h" 14 | 15 | // Digital I/O used 16 | #define SD_CS 5 17 | #define SPI_MOSI 23 18 | #define SPI_MISO 19 19 | #define SPI_SCK 18 20 | #define I2S_DOUT 25 21 | #define I2S_BCLK 27 22 | #define I2S_LRC 26 23 | 24 | Audio audio; 25 | 26 | String ssid = "*******"; 27 | String password = "*******"; 28 | 29 | void setup() { 30 | pinMode(SD_CS, OUTPUT); digitalWrite(SD_CS, HIGH); 31 | SPI.begin(SPI_SCK, SPI_MISO, SPI_MOSI); 32 | Serial.begin(115200); 33 | SD.begin(SD_CS); 34 | WiFi.disconnect(); 35 | WiFi.mode(WIFI_STA); 36 | WiFi.begin(ssid.c_str(), password.c_str()); 37 | while (WiFi.status() != WL_CONNECTED) delay(1500); 38 | audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT); 39 | audio.setVolume(21); // 0...21 40 | 41 | // audio.connecttoFS(SD, "/320k_test.mp3"); 42 | // audio.connecttoFS(SD, "test.wav"); 43 | // audio.connecttohost("http://www.wdr.de/wdrlive/media/einslive.m3u"); 44 | // audio.connecttohost("http://macslons-irish-pub-radio.com/media.asx"); 45 | // audio.connecttohost("http://mp3.ffh.de/radioffh/hqlivestream.aac"); // 128k aac 46 | audio.connecttohost("http://mp3.ffh.de/radioffh/hqlivestream.mp3"); // 128k mp3 47 | // audio.connecttospeech("Wenn die Hunde schlafen, kann der Wolf gut Schafe stehlen.", "de"); 48 | // audio.connecttohost("http://media.ndr.de/download/podcasts/podcast4161/AU-20190404-0844-1700.mp3"); // podcast 49 | } 50 | 51 | void loop() 52 | { 53 | audio.loop(); 54 | } 55 | 56 | // optional 57 | void audio_info(const char *info){ 58 | Serial.print("info "); Serial.println(info); 59 | } 60 | void audio_id3data(const char *info){ //id3 metadata 61 | Serial.print("id3data ");Serial.println(info); 62 | } 63 | void audio_eof_mp3(const char *info){ //end of file 64 | Serial.print("eof_mp3 ");Serial.println(info); 65 | } 66 | void audio_showstation(const char *info){ 67 | Serial.print("station ");Serial.println(info); 68 | } 69 | void audio_showstreaminfo(const char *info){ 70 | Serial.print("streaminfo ");Serial.println(info); 71 | } 72 | void audio_showstreamtitle(const char *info){ 73 | Serial.print("streamtitle ");Serial.println(info); 74 | } 75 | void audio_bitrate(const char *info){ 76 | Serial.print("bitrate ");Serial.println(info); 77 | } 78 | void audio_commercial(const char *info){ //duration in sec 79 | Serial.print("commercial ");Serial.println(info); 80 | } 81 | void audio_icyurl(const char *info){ //homepage 82 | Serial.print("icyurl ");Serial.println(info); 83 | } 84 | void audio_lasthost(const char *info){ //stream URL played 85 | Serial.print("lasthost ");Serial.println(info); 86 | } 87 | void audio_eof_speech(const char *info){ 88 | Serial.print("eof_speech ");Serial.println(info); 89 | } 90 | 91 | ```` 92 | Breadboard 93 | ![Breadboard](https://github.com/schreibfaul1/ESP32-audioI2S/blob/master/additional_info/Breadboard.jpg) 94 | Wiring 95 | ![Wiring](https://github.com/schreibfaul1/ESP32-audioI2S/blob/master/additional_info/ESP32_I2S_PCM5102A.JPG) 96 | Impulse diagram 97 | ![Impulse diagram](https://github.com/schreibfaul1/ESP32-audioI2S/blob/master/additional_info/Impulsdiagramm.jpg) 98 | -------------------------------------------------------------------------------- /old-src/esp32_mp3/ESP32-audioI2S/additional_info/Testfiles/320k_test.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Makerfabs/Project_MakePython_Audio_Music/3675eecd3b1562700e8ce36420fdf39be5d961e1/old-src/esp32_mp3/ESP32-audioI2S/additional_info/Testfiles/320k_test.mp3 -------------------------------------------------------------------------------- /old-src/esp32_mp3/ESP32-audioI2S/additional_info/Testfiles/LightMusic.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Makerfabs/Project_MakePython_Audio_Music/3675eecd3b1562700e8ce36420fdf39be5d961e1/old-src/esp32_mp3/ESP32-audioI2S/additional_info/Testfiles/LightMusic.wav -------------------------------------------------------------------------------- /old-src/esp32_mp3/ESP32-audioI2S/additional_info/Testfiles/MoonlightBay.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Makerfabs/Project_MakePython_Audio_Music/3675eecd3b1562700e8ce36420fdf39be5d961e1/old-src/esp32_mp3/ESP32-audioI2S/additional_info/Testfiles/MoonlightBay.mp3 -------------------------------------------------------------------------------- /old-src/esp32_mp3/ESP32-audioI2S/additional_info/Testfiles/PrettyWorld.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Makerfabs/Project_MakePython_Audio_Music/3675eecd3b1562700e8ce36420fdf39be5d961e1/old-src/esp32_mp3/ESP32-audioI2S/additional_info/Testfiles/PrettyWorld.wav -------------------------------------------------------------------------------- /old-src/esp32_mp3/ESP32-audioI2S/additional_info/Testfiles/beep.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Makerfabs/Project_MakePython_Audio_Music/3675eecd3b1562700e8ce36420fdf39be5d961e1/old-src/esp32_mp3/ESP32-audioI2S/additional_info/Testfiles/beep.mp3 -------------------------------------------------------------------------------- /old-src/esp32_mp3/ESP32-audioI2S/additional_info/Testfiles/click.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Makerfabs/Project_MakePython_Audio_Music/3675eecd3b1562700e8ce36420fdf39be5d961e1/old-src/esp32_mp3/ESP32-audioI2S/additional_info/Testfiles/click.mp3 -------------------------------------------------------------------------------- /old-src/esp32_mp3/ESP32-audioI2S/additional_info/Testfiles/seconds-CBR.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Makerfabs/Project_MakePython_Audio_Music/3675eecd3b1562700e8ce36420fdf39be5d961e1/old-src/esp32_mp3/ESP32-audioI2S/additional_info/Testfiles/seconds-CBR.mp3 -------------------------------------------------------------------------------- /old-src/esp32_mp3/ESP32-audioI2S/additional_info/Testfiles/seconds-VBR.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Makerfabs/Project_MakePython_Audio_Music/3675eecd3b1562700e8ce36420fdf39be5d961e1/old-src/esp32_mp3/ESP32-audioI2S/additional_info/Testfiles/seconds-VBR.mp3 -------------------------------------------------------------------------------- /old-src/esp32_mp3/ESP32-audioI2S/additional_info/Testfiles/test.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Makerfabs/Project_MakePython_Audio_Music/3675eecd3b1562700e8ce36420fdf39be5d961e1/old-src/esp32_mp3/ESP32-audioI2S/additional_info/Testfiles/test.wav -------------------------------------------------------------------------------- /old-src/esp32_mp3/ESP32-audioI2S/additional_info/Testfiles/test_8bit_mono.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Makerfabs/Project_MakePython_Audio_Music/3675eecd3b1562700e8ce36420fdf39be5d961e1/old-src/esp32_mp3/ESP32-audioI2S/additional_info/Testfiles/test_8bit_mono.wav -------------------------------------------------------------------------------- /old-src/esp32_mp3/ESP32-audioI2S/additional_info/Testfiles/test_8bit_stereo.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Makerfabs/Project_MakePython_Audio_Music/3675eecd3b1562700e8ce36420fdf39be5d961e1/old-src/esp32_mp3/ESP32-audioI2S/additional_info/Testfiles/test_8bit_stereo.wav -------------------------------------------------------------------------------- /old-src/esp32_mp3/ESP32-audioI2S/additional_info/Testfiles/wobble.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Makerfabs/Project_MakePython_Audio_Music/3675eecd3b1562700e8ce36420fdf39be5d961e1/old-src/esp32_mp3/ESP32-audioI2S/additional_info/Testfiles/wobble.mp3 -------------------------------------------------------------------------------- /old-src/esp32_mp3/ESP32-audioI2S/examples/ESP32-A1S/A1S.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Makerfabs/Project_MakePython_Audio_Music/3675eecd3b1562700e8ce36420fdf39be5d961e1/old-src/esp32_mp3/ESP32-audioI2S/examples/ESP32-A1S/A1S.pdf -------------------------------------------------------------------------------- /old-src/esp32_mp3/ESP32-audioI2S/examples/ESP32-A1S/ESP32-A1S Product Specification.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Makerfabs/Project_MakePython_Audio_Music/3675eecd3b1562700e8ce36420fdf39be5d961e1/old-src/esp32_mp3/ESP32-audioI2S/examples/ESP32-A1S/ESP32-A1S Product Specification.pdf -------------------------------------------------------------------------------- /old-src/esp32_mp3/ESP32-audioI2S/examples/ESP32-A1S/ESP32-Aduio-Kit WiFi+ bluetooth Module ESP32.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Makerfabs/Project_MakePython_Audio_Music/3675eecd3b1562700e8ce36420fdf39be5d961e1/old-src/esp32_mp3/ESP32-audioI2S/examples/ESP32-A1S/ESP32-Aduio-Kit WiFi+ bluetooth Module ESP32.jpeg -------------------------------------------------------------------------------- /old-src/esp32_mp3/ESP32-audioI2S/examples/ESP32-A1S/ESP32_A1S.ino: -------------------------------------------------------------------------------- 1 | // found this sketch on https://www.mikrocontroller.net/topic/474383 2 | // thanks to Michael U. (amiga) 3 | 4 | #include "Arduino.h" 5 | #include "WiFi.h" 6 | #include "SPI.h" 7 | #include "SD.h" 8 | #include "FS.h" 9 | #include "Wire.h" 10 | #include "AC101.h" //https://github.com/Yveaux/AC101 11 | #include "Audio.h" //https://github.com/schreibfaul1/ESP32-audioI2S 12 | 13 | 14 | // SPI GPIOs 15 | #define SD_CS 13 16 | #define SPI_MOSI 15 17 | #define SPI_MISO 2 18 | #define SPI_SCK 14 19 | 20 | // I2S GPIOs, the names refer on AC101 21 | #define I2S_DSIN 25 22 | #define I2S_BCLK 27 23 | #define I2S_LRC 26 24 | #define I2S_MCLK 0 25 | #define I2S_DOUT 35 26 | 27 | // I2C GPIOs 28 | #define IIC_CLK 32 29 | #define IIC_DATA 33 30 | 31 | // Tasten 32 | // #define BUTTON_2_PIN 13 // shared mit SPI_CS 33 | #define BUTTON_3_PIN 19 34 | #define BUTTON_4_PIN 23 35 | #define BUTTON_5_PIN 18 // Stop 36 | #define BUTTON_6_PIN 5 // Play 37 | 38 | // Verstärker enable 39 | #define GPIO_PA_EN 21 40 | 41 | //Switch S1: 1-OFF, 2-ON, 3-ON, 4-OFF, 5-OFF 42 | 43 | String ssid = "xxxxxxxxx"; 44 | String password = "xxxxxxxxx"; 45 | 46 | static AC101 ac; 47 | int volume = 40; // 0...100 48 | 49 | Audio audio; 50 | 51 | //##################################################################### 52 | 53 | void setup() 54 | { 55 | Serial.begin(115200); 56 | Serial.println("\r\nReset"); 57 | Serial.printf_P(PSTR("Free mem=%d\n"), ESP.getFreeHeap()); 58 | 59 | pinMode(SD_CS, OUTPUT); 60 | digitalWrite(SD_CS, HIGH); 61 | SPI.begin(SPI_SCK, SPI_MISO, SPI_MOSI); 62 | SPI.setFrequency(1000000); 63 | 64 | SD.begin(SD_CS); 65 | 66 | WiFi.mode(WIFI_STA); 67 | WiFi.begin(ssid.c_str(), password.c_str()); 68 | 69 | while (WiFi.status() != WL_CONNECTED) 70 | { 71 | Serial.print("."); 72 | delay(100); 73 | } 74 | 75 | Serial.printf_P(PSTR("Connected\r\nRSSI: ")); 76 | Serial.print(WiFi.RSSI()); 77 | Serial.print(" IP: "); 78 | Serial.println(WiFi.localIP()); 79 | 80 | Serial.printf("Connect to AC101 codec... "); 81 | while (not ac.begin(IIC_DATA, IIC_CLK)) 82 | { 83 | Serial.printf("Failed!\n"); 84 | delay(1000); 85 | } 86 | Serial.printf("OK\n"); 87 | 88 | ac.SetVolumeSpeaker(volume); 89 | ac.SetVolumeHeadphone(volume); 90 | // ac.DumpRegisters(); 91 | 92 | // Enable amplifier 93 | pinMode(GPIO_PA_EN, OUTPUT); 94 | digitalWrite(GPIO_PA_EN, HIGH); 95 | 96 | audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DSIN); 97 | audio.setVolume(10); // 0...21 98 | 99 | audio.connecttoFS(SD, "/320k_test.mp3"); 100 | // audio.connecttoSD("/Banana Boat Song - Harry Belafonte.mp3"); 101 | // audio.connecttohost("http://mp3channels.webradio.antenne.de:80/oldies-but-goldies"); 102 | // audio.connecttohost("http://dg-rbb-http-dus-dtag-cdn.cast.addradio.de/rbb/antennebrandenburg/live/mp3/128/stream.mp3"); 103 | // audio.connecttospeech("Wenn die Hunde schlafen, kann der Wolf gut Schafe stehlen.", "de"); 104 | 105 | } 106 | 107 | //----------------------------------------------------------------------- 108 | 109 | void loop() 110 | { 111 | audio.loop(); 112 | } 113 | 114 | // optional 115 | void audio_info(const char *info){ 116 | Serial.print("info "); Serial.println(info); 117 | } 118 | void audio_id3data(const char *info){ //id3 metadata 119 | Serial.print("id3data ");Serial.println(info); 120 | } 121 | void audio_eof_mp3(const char *info){ //end of file 122 | Serial.print("eof_mp3 ");Serial.println(info); 123 | } 124 | void audio_showstation(const char *info){ 125 | Serial.print("station ");Serial.println(info); 126 | } 127 | void audio_showstreaminfo(const char *info){ 128 | Serial.print("streaminfo ");Serial.println(info); 129 | } 130 | void audio_showstreamtitle(const char *info){ 131 | Serial.print("streamtitle ");Serial.println(info); 132 | } 133 | void audio_bitrate(const char *info){ 134 | Serial.print("bitrate ");Serial.println(info); 135 | } 136 | void audio_commercial(const char *info){ //duration in sec 137 | Serial.print("commercial ");Serial.println(info); 138 | } 139 | void audio_icyurl(const char *info){ //homepage 140 | Serial.print("icyurl ");Serial.println(info); 141 | } 142 | void audio_lasthost(const char *info){ //stream URL played 143 | Serial.print("lasthost ");Serial.println(info); 144 | } 145 | void audio_eof_speech(const char *info){ 146 | Serial.print("eof_speech ");Serial.println(info); 147 | } 148 | -------------------------------------------------------------------------------- /old-src/esp32_mp3/ESP32-audioI2S/examples/I2Saudio.ino: -------------------------------------------------------------------------------- 1 | #include "Arduino.h" 2 | #include "WiFiMulti.h" 3 | #include "Audio.h" 4 | #include "SPI.h" 5 | #include "SD.h" 6 | #include "FS.h" 7 | 8 | // Digital I/O used 9 | #define SD_CS 5 10 | #define SPI_MOSI 23 11 | #define SPI_MISO 19 12 | #define SPI_SCK 18 13 | #define I2S_DOUT 25 14 | #define I2S_BCLK 27 15 | #define I2S_LRC 26 16 | 17 | Audio audio; 18 | WiFiMulti wifiMulti; 19 | 20 | String ssid = "xxxxxx"; 21 | String password = "xxxxxx"; 22 | 23 | void setup() { 24 | pinMode(SD_CS, OUTPUT); digitalWrite(SD_CS, HIGH); 25 | SPI.begin(SPI_SCK, SPI_MISO, SPI_MOSI); 26 | SPI.setFrequency(1000000); 27 | Serial.begin(115200); 28 | SD.begin(SD_CS); 29 | WiFi.mode(WIFI_STA); 30 | wifiMulti.addAP(ssid.c_str(), password.c_str()); 31 | wifiMulti.run(); 32 | if(WiFi.status() != WL_CONNECTED){ 33 | WiFi.disconnect(true); 34 | wifiMulti.run(); 35 | } 36 | audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT); 37 | audio.setVolume(12); // 0...21 38 | 39 | //audio.connecttoFS(SD, "/320k_test.mp3"); 40 | //audio.connecttohost("www.wdr.de/wdrlive/media/einslive.m3u"); 41 | //audio.connecttohost("dg-ais-eco-http-fra-eco-cdn.cast.addradio.de/hellwegradio/west/mp3/high"); 42 | //audio.connecttohost("http://macslons-irish-pub-radio.com/media.asx"); 43 | //audio.connecttospeech("Wenn die Hunde schlafen, kann der Wolf gut Schafe stehlen.", "de"); 44 | } 45 | 46 | void loop() 47 | { 48 | audio.loop(); 49 | } 50 | 51 | // optional 52 | void audio_info(const char *info){ 53 | Serial.print("info "); Serial.println(info); 54 | } 55 | void audio_id3data(const char *info){ //id3 metadata 56 | Serial.print("id3data ");Serial.println(info); 57 | } 58 | void audio_eof_mp3(const char *info){ //end of file 59 | Serial.print("eof_mp3 ");Serial.println(info); 60 | } 61 | void audio_showstation(const char *info){ 62 | Serial.print("station ");Serial.println(info); 63 | } 64 | void audio_showstreaminfo(const char *info){ 65 | Serial.print("streaminfo ");Serial.println(info); 66 | } 67 | void audio_showstreamtitle(const char *info){ 68 | Serial.print("streamtitle ");Serial.println(info); 69 | } 70 | void audio_bitrate(const char *info){ 71 | Serial.print("bitrate ");Serial.println(info); 72 | } 73 | void audio_commercial(const char *info){ //duration in sec 74 | Serial.print("commercial ");Serial.println(info); 75 | } 76 | void audio_icyurl(const char *info){ //homepage 77 | Serial.print("icyurl ");Serial.println(info); 78 | } 79 | void audio_lasthost(const char *info){ //stream URL played 80 | Serial.print("lasthost ");Serial.println(info); 81 | } 82 | void audio_eof_speech(const char *info){ 83 | Serial.print("eof_speech ");Serial.println(info); 84 | } 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /old-src/esp32_mp3/ESP32-audioI2S/examples/M5Stack.ino: -------------------------------------------------------------------------------- 1 | 2 | // M5Stack Node support 3 | // thanks to Cellie - issue #35 25.Apr.2020 4 | // M5Stack boards also need a MCLK signal on GPIO0. 5 | 6 | #include /* https://github.com/CelliesProjects/wm8978-esp32 */ 7 | #include /* https://github.com/schreibfaul1/ESP32-audioI2S */ 8 | 9 | /* M5Stack Node WM8978 I2C pins */ 10 | #define I2C_SDA 21 11 | #define I2C_SCL 22 12 | 13 | /* M5Stack Node I2S pins */ 14 | #define I2S_BCK 5 15 | #define I2S_WS 13 16 | #define I2S_DOUT 2 17 | #define I2S_DIN 34 18 | 19 | /* M5Stack WM8978 MCLK gpio number and frequency */ 20 | #define I2S_MCLKPIN 0 21 | #define I2S_MFREQ (24 * 1000 * 1000) 22 | 23 | WM8978 dac; 24 | Audio audio; 25 | 26 | void setup() { 27 | /* Setup wm8978 I2C interface */ 28 | if (!dac.begin(I2C_SDA, I2C_SCL)) { 29 | ESP_LOGE(TAG, "Error setting up dac. System halted"); 30 | while (1) delay(100); 31 | } 32 | /* Setup wm8978 MCLK on gpio - for example M5Stack Node needs a 24Mhz clock on gpio 0 */ 33 | dac.setPinClockFreq(I2S_MCLKPIN, I2S_MFREQ); 34 | 35 | /* Setup wm8978 I2S interface */ 36 | audio.setPinout(I2S_BCK, I2S_WS, I2S_DOUT, I2S_DIN); 37 | 38 | WiFi.begin("xxx", "xxx"); 39 | while (!WiFi.isConnected()) { 40 | delay(10); 41 | } 42 | ESP_LOGI(TAG, "Connected"); 43 | 44 | ESP_LOGI(TAG, "Starting MP3...\n"); 45 | audio.connecttohost("http://icecast.omroep.nl/3fm-bb-mp3"); 46 | 47 | dac.setSPKvol(40); /* max 63 */ 48 | dac.setHPvol(32, 32); 49 | } 50 | 51 | void loop() { 52 | audio.loop(); 53 | } 54 | -------------------------------------------------------------------------------- /old-src/esp32_mp3/ESP32-audioI2S/examples/Simple WiFI Radio/Simple_WiFi_Radio.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "tft.h" //see my repository at github "https://github.com/schreibfaul1/ESP32-TFT-Library-ILI9486" 6 | #include "Audio.h" //see my repository at github "https://github.com/schreibfaul1/ESP32-audioI2S" 7 | 8 | #define TFT_CS 22 9 | #define TFT_DC 21 10 | #define TP_CS 16 11 | #define TP_IRQ 39 12 | #define SPI_MOSI 23 13 | #define SPI_MISO 19 14 | #define SPI_SCK 18 15 | #define I2S_DOUT 25 16 | #define I2S_BCLK 27 17 | #define I2S_LRC 26 18 | 19 | Preferences pref; 20 | TFT tft; 21 | TP tp(TP_CS, TP_IRQ); 22 | Audio audio; 23 | 24 | String ssid = "*****"; 25 | String password = "*****"; 26 | 27 | String stations[] ={ 28 | "0n-80s.radionetz.de:8000/0n-70s.mp3", 29 | "mediaserv30.live-streams.nl:8000/stream", 30 | "www.surfmusic.de/m3u/100-5-das-hitradio,4529.m3u", 31 | "stream.1a-webradio.de/deutsch/mp3-128/vtuner-1a", 32 | "mp3.ffh.de/radioffh/hqlivestream.aac", // 128k aac 33 | "www.antenne.de/webradio/antenne.m3u", 34 | "listen.rusongs.ru/ru-mp3-128", 35 | "edge.audio.3qsdn.com/senderkw-mp3", 36 | "macslons-irish-pub-radio.com/media.asx", 37 | }; 38 | 39 | //some global variables 40 | 41 | uint8_t max_volume = 21; 42 | uint8_t max_stations = 0; //will be set later 43 | uint8_t cur_station = 0; //current station(nr), will be set later 44 | uint8_t cur_volume = 0; //will be set from stored preferences 45 | int8_t cur_btn =-1; //current button (, -1 means idle) 46 | 47 | enum action{VOLUME_UP=0, VOLUME_DOWN=1, STATION_UP=2, STATION_DOWN=3}; 48 | enum staus {RELEASED=0, PRESSED=1}; 49 | 50 | struct _btns{ 51 | uint16_t x; //PosX 52 | uint16_t y; //PosY 53 | uint16_t w; //Width 54 | uint16_t h; //Hight 55 | uint8_t a; //Action 56 | uint8_t s; //Status 57 | }; 58 | typedef _btns btns; 59 | 60 | btns btn[4]; 61 | 62 | //************************************************************************************************** 63 | // G U I * 64 | //************************************************************************************************** 65 | void draw_button(btns b){ 66 | uint16_t color=TFT_BLACK; 67 | uint8_t r=4, o=r*3; 68 | if(b.s==RELEASED) color=TFT_GOLD; 69 | if(b.s==PRESSED) color=TFT_DEEPSKYBLUE; 70 | tft.drawRoundRect(b.x, b.y, b.w, b.h, r, color); 71 | switch(b.a){ 72 | case VOLUME_UP: 73 | tft.fillTriangle(b.x+b.w/2, b.y+o, b.x+o, b.y+b.h-o, b.x+b.w-o, b.y+b.h-o, color); break; 74 | case VOLUME_DOWN: 75 | tft.fillTriangle(b.x+o, b.y+o, b.x+b.w/2, b.y+b.h-o, b.x+b.w-o, b.y+o, color); break; 76 | case STATION_UP: 77 | tft.fillTriangle(b.x+o, b.y+o, b.x+o, b.y+b.h-o, b.x+b.w-o, b.y+b.h/2, color); break; 78 | case STATION_DOWN: 79 | tft.fillTriangle(b.x+b.w-o, b.y+o, b.x+o, b.y+b.h/2, b.x+b.w-o, b.y+b.h-o, color); break; 80 | } 81 | } 82 | void write_stationNr(uint8_t nr){ 83 | tft.fillRect(80, 250, 80, 60, TFT_BLACK); 84 | String snr = String(nr); 85 | if(snr.length()<2) snr = "0"+snr; 86 | tft.setCursor(98, 255); 87 | tft.setFont(Garamond44x54); 88 | tft.setTextColor(TFT_YELLOW); 89 | tft.print(snr); 90 | } 91 | void write_volume(uint8_t vol){ 92 | tft.fillRect(320, 250, 80, 60, TFT_BLACK); 93 | String svol = String(vol); 94 | if(svol.length()<2) svol = "0"+svol; 95 | tft.setCursor(338, 255); 96 | tft.setFont(Garamond44x54); 97 | tft.setTextColor(TFT_YELLOW); 98 | tft.print(svol); 99 | } 100 | void write_stationName(String sName){ 101 | tft.fillRect(0, 0, 480, 100, TFT_BLACK); 102 | tft.setFont(Times_New_Roman43x35); 103 | tft.setTextColor(TFT_CORNSILK); 104 | tft.setCursor(20, 20); 105 | tft.print(sName); 106 | } 107 | void write_streamTitle(String sTitle){ 108 | tft.fillRect(0, 100, 480, 150, TFT_BLACK); 109 | tft.setFont(Times_New_Roman43x35); 110 | tft.setTextColor(TFT_LIGHTBLUE); 111 | tft.setCursor(20, 100); 112 | tft.print(sTitle); 113 | } 114 | //************************************************************************************************** 115 | // S E T U P * 116 | //************************************************************************************************** 117 | void setup() { 118 | btn[0].x= 20; btn[0].y=250; btn[0].w=60; btn[0].h=60; btn[0].a=STATION_DOWN; btn[0].s=RELEASED; 119 | btn[1].x=160; btn[1].y=250; btn[1].w=60; btn[1].h=60; btn[1].a=STATION_UP; btn[1].s=RELEASED; 120 | btn[2].x=260; btn[2].y=250; btn[2].w=60; btn[2].h=60; btn[2].a=VOLUME_UP; btn[2].s=RELEASED; 121 | btn[3].x=400; btn[3].y=250; btn[3].w=60; btn[3].h=60; btn[3].a=VOLUME_DOWN; btn[3].s=RELEASED; 122 | max_stations= sizeof(stations)/sizeof(stations[0]); log_i("max stations %i", max_stations); 123 | Serial.begin(115200); 124 | SPI.begin(SPI_SCK, SPI_MISO, SPI_MOSI); 125 | pref.begin("WebRadio", false); // instance of preferences for defaults (station, volume ...) 126 | if(pref.getShort("volume", 1000) == 1000){ // if that: pref was never been initialized 127 | pref.putShort("volume", 10); 128 | pref.putShort("station", 0); 129 | } 130 | else{ // get the stored values 131 | cur_station = pref.getShort("station"); 132 | cur_volume = pref.getShort("volume"); 133 | } 134 | WiFi.mode(WIFI_STA); 135 | while (WiFi.status() != WL_CONNECTED){ 136 | WiFi.begin(ssid.c_str(), password.c_str()); 137 | delay(1500); 138 | } 139 | log_i("Connect to %s", WiFi.SSID().c_str()); 140 | tft.begin(TFT_CS, TFT_DC, SPI_MOSI, SPI_MISO, SPI_SCK); 141 | tft.setRotation(3); 142 | tp.setRotation(3); 143 | tft.setFont(Times_New_Roman43x35); 144 | tft.fillScreen(TFT_BLACK); 145 | audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT); 146 | audio.setVolume(cur_volume); // 0...21 147 | audio.connecttohost(stations[cur_station]); 148 | for(uint8_t i=0; i<(sizeof(btn)/sizeof(*btn)); i++) draw_button(btn[i]); 149 | write_volume(cur_volume); 150 | write_stationNr(cur_station); 151 | } 152 | //************************************************************************************************** 153 | // L O O P * 154 | //************************************************************************************************** 155 | void loop() 156 | { 157 | audio.loop(); 158 | tp.loop(); 159 | } 160 | //************************************************************************************************** 161 | // E V E N T S * 162 | //************************************************************************************************** 163 | void audio_info(const char *info){ 164 | Serial.print("audio_info: "); Serial.println(info); 165 | } 166 | void audio_showstation(const char *info){ 167 | write_stationName(String(info)); 168 | } 169 | void audio_showstreamtitle(const char *info){ 170 | String sinfo=String(info); 171 | sinfo.replace("|", "\n"); 172 | write_streamTitle(sinfo); 173 | } 174 | 175 | void tp_pressed(uint16_t x, uint16_t y){ 176 | for(uint8_t i=0; i<(sizeof(btn)/sizeof(*btn)); i++){ 177 | if(x>btn[i].x && (xbtn[i].y && (y0){ 198 | cur_volume-- ; 199 | write_volume(cur_volume); 200 | audio.setVolume(cur_volume); 201 | pref.putShort("volume", cur_volume);} // store the current volume in nvs 202 | break; 203 | case STATION_UP: if(cur_station0){ 211 | cur_station--; 212 | write_stationNr(cur_station); 213 | tft.fillRect(0, 0, 480, 250, TFT_BLACK); 214 | audio.connecttohost(stations[cur_station]); 215 | pref.putShort("station", cur_station);} // store the current station in nvs 216 | break; 217 | } 218 | } 219 | cur_btn=-1; 220 | } 221 | -------------------------------------------------------------------------------- /old-src/esp32_mp3/ESP32-audioI2S/examples/Simple WiFI Radio/Simple_WiFi_Radio.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Makerfabs/Project_MakePython_Audio_Music/3675eecd3b1562700e8ce36420fdf39be5d961e1/old-src/esp32_mp3/ESP32-audioI2S/examples/Simple WiFI Radio/Simple_WiFi_Radio.jpg -------------------------------------------------------------------------------- /old-src/esp32_mp3/ESP32-audioI2S/examples/Simple WiFI Radio/Simple_WiFi_Radio_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Makerfabs/Project_MakePython_Audio_Music/3675eecd3b1562700e8ce36420fdf39be5d961e1/old-src/esp32_mp3/ESP32-audioI2S/examples/Simple WiFI Radio/Simple_WiFi_Radio_1.jpg -------------------------------------------------------------------------------- /old-src/esp32_mp3/ESP32-audioI2S/examples/Simple WiFI Radio/Simple_WiFi_Radio_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Makerfabs/Project_MakePython_Audio_Music/3675eecd3b1562700e8ce36420fdf39be5d961e1/old-src/esp32_mp3/ESP32-audioI2S/examples/Simple WiFI Radio/Simple_WiFi_Radio_2.jpg -------------------------------------------------------------------------------- /old-src/esp32_mp3/ESP32-audioI2S/examples/Simple WiFI Radio/Simple_WiFi_Radio_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Makerfabs/Project_MakePython_Audio_Music/3675eecd3b1562700e8ce36420fdf39be5d961e1/old-src/esp32_mp3/ESP32-audioI2S/examples/Simple WiFI Radio/Simple_WiFi_Radio_3.jpg -------------------------------------------------------------------------------- /old-src/esp32_mp3/ESP32-audioI2S/examples/Simple WiFI Radio/Simple_WiFi_Radio_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Makerfabs/Project_MakePython_Audio_Music/3675eecd3b1562700e8ce36420fdf39be5d961e1/old-src/esp32_mp3/ESP32-audioI2S/examples/Simple WiFI Radio/Simple_WiFi_Radio_4.jpg -------------------------------------------------------------------------------- /old-src/esp32_mp3/ESP32-audioI2S/keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For Ultrasound 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | Audio KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | 15 | audio_bitrate KEYWORD2 16 | audio_commercial KEYWORD2 17 | audio_eof_mp3 KEYWORD2 18 | audio_eof_speech KEYWORD2 19 | audio_icyurl KEYWORD2 20 | audio_info KEYWORD2 21 | audio_id3data KEYWORD2 22 | audio_lasthost KEYWORD2 23 | audio_showstreamtitle KEYWORD2 24 | audio_showstation KEYWORD2 25 | audio_showstreaminfo KEYWORD2 26 | audio_eof_stream KEYWORD2 27 | audioFileSeek KEYWORD2 28 | connecttoSD KEYWORD2 29 | connecttoFS KEYWORD2 30 | connecttohost KEYWORD2 31 | connecttospeech KEYWORD2 32 | getAudioCurrentTime KEYWORD2 33 | getAudioFileDuration KEYWORD2 34 | getDatamode KEYWORD2 35 | getFilePos KEYWORD2 36 | getFileSize KEYWORD2 37 | getVolume KEYWORD2 38 | loop KEYWORD2 39 | pauseResume KEYWORD2 40 | setDatamode KEYWORD2 41 | setFilePos KEYWORD2 42 | setPinout KEYWORD2 43 | setVolume KEYWORD2 44 | stopSong KEYWORD2 45 | streamavail KEYWORD2 46 | isRunning KEYWORD2 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | ####################################### 55 | # Constants (LITERAL1) 56 | ####################################### 57 | -------------------------------------------------------------------------------- /old-src/esp32_mp3/ESP32-audioI2S/library.properties: -------------------------------------------------------------------------------- 1 | name=ESP32-audioI2S-master 2 | version=2.0.0 3 | author=schreibfaul1 4 | maintainer=schreibfaul1 5 | sentence=With this library You can easily build a WebRadio with a ESP32 board and a I2S-module. 6 | paragraph=Plays google tts, mp3 webradio, playlists can be m3u, pls or asx. Data format can be only mp3. It can also play MP3 files from a SD Card. 7 | category=Device Control 8 | url=https://github.com/schreibfaul1/ESP32-audioI2S 9 | architectures=esp32 10 | -------------------------------------------------------------------------------- /old-src/esp32_mp3/ESP32-audioI2S/src/Audio.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Audio.h 3 | * 4 | * Created on: Oct 26,2018 5 | * Updated on: Jul 15,2020 6 | * Author: Wolle (schreibfaul1) 7 | */ 8 | 9 | #ifndef AUDIO_H_ 10 | #define AUDIO_H_ 11 | 12 | #include "Arduino.h" 13 | #include "SPI.h" 14 | #include "SD.h" 15 | #include "FS.h" 16 | #include "WiFiClientSecure.h" 17 | #include "driver/i2s.h" 18 | 19 | extern __attribute__((weak)) void audio_info(const char*); 20 | extern __attribute__((weak)) void audio_id3data(const char*); //ID3 metadata 21 | extern __attribute__((weak)) void audio_eof_mp3(const char*); //end of mp3 file 22 | extern __attribute__((weak)) void audio_showstreamtitle(const char*); 23 | extern __attribute__((weak)) void audio_showstation(const char*); 24 | extern __attribute__((weak)) void audio_showstreaminfo(const char*); 25 | extern __attribute__((weak)) void audio_bitrate(const char*); 26 | extern __attribute__((weak)) void audio_commercial(const char*); 27 | extern __attribute__((weak)) void audio_icyurl(const char*); 28 | extern __attribute__((weak)) void audio_lasthost(const char*); 29 | extern __attribute__((weak)) void audio_eof_speech(const char*); 30 | extern __attribute__((weak)) void audio_eof_stream(const char*); // The webstream comes to an end 31 | 32 | #define AUDIO_HEADER 2 //const for datamode 33 | #define AUDIO_DATA 4 34 | #define AUDIO_METADATA 8 35 | #define AUDIO_PLAYLISTINIT 16 36 | #define AUDIO_PLAYLISTHEADER 32 37 | #define AUDIO_PLAYLISTDATA 64 38 | #define AUDIO_SWM 128 39 | 40 | // 41 | 42 | 43 | class Audio { 44 | 45 | public: 46 | Audio(); 47 | ~Audio(); 48 | bool connecttoFS(fs::FS &fs, String file); 49 | bool connecttoSD(String sdfile); 50 | bool connecttohost(String host); 51 | bool connecttospeech(String speech, String lang); 52 | void loop(); 53 | uint32_t getFileSize(); 54 | uint32_t getFilePos(); 55 | uint32_t getSampleRate(); 56 | uint8_t getBitsPerSample(); 57 | uint8_t getChannels(); 58 | 59 | /** 60 | * @brief Get the audio file duration in seconds 61 | * 62 | * @return uint32_t file duration in seconds, 0 if no file active 63 | */ 64 | uint32_t getAudioFileDuration(); 65 | /** 66 | * @brief Get the current plying time in seconds 67 | * 68 | * @return uint32_t current second of audio file, 0 if no file active 69 | */ 70 | uint32_t getAudioCurrentTime(); 71 | bool setFilePos(uint32_t pos); 72 | /** 73 | * @brief audioFileSeek seeks the file in both directions 74 | * 75 | * @param[in] speed 76 | * speed > 0 : fast-forward 77 | * speed < 0 : fast-rewind 78 | * @return true if audio file active and speed is valid, otherwise false 79 | */ 80 | bool audioFileSeek(const int8_t speed); 81 | bool setPinout(uint8_t BCLK, uint8_t LRC, uint8_t DOUT, int8_t DIN=I2S_PIN_NO_CHANGE); 82 | void stopSong(); 83 | /** 84 | * @brief pauseResume pauses current playback 85 | * 86 | * @return true if audio file or stream is active, false otherwise 87 | */ 88 | bool pauseResume(); 89 | 90 | void setVolume(uint8_t vol); 91 | uint8_t getVolume(); 92 | inline uint8_t getDatamode(){return m_datamode;} 93 | inline void setDatamode(uint8_t dm){m_datamode=dm;} 94 | inline uint32_t streamavail() {if(m_f_ssl==false) return client.available(); else return clientsecure.available();} 95 | bool isRunning() {return m_f_running;} 96 | 97 | private: 98 | void reset(); // free buffers and set defaults 99 | void processLocalFile(); 100 | void processWebStream(); 101 | int sendBytes(uint8_t *data, size_t len); 102 | void compute_audioCurrentTime(int bd); 103 | void printDecodeError(int r); 104 | void readID3Metadata(); 105 | bool setSampleRate(uint32_t hz); 106 | bool setBitsPerSample(int bits); 107 | bool setChannels(int channels); 108 | bool playChunk(); 109 | bool playSample(int16_t sample[2]) ; 110 | void playI2Sremains(); 111 | int16_t Gain(int16_t s); 112 | bool fill_InputBuf(); 113 | void showstreamtitle(const char *ml, bool full); 114 | bool chkhdrline(const char* str); 115 | void handlebyte(uint8_t b); 116 | esp_err_t I2Sstart(uint8_t i2s_num); 117 | esp_err_t I2Sstop(uint8_t i2s_num); 118 | char* lltoa(long long val, int base); 119 | long long int XL (long long int a, const char* b); 120 | String urlencode(String str); 121 | 122 | private: 123 | enum : int { APLL_AUTO = -1, APLL_ENABLE = 1, APLL_DISABLE = 0 }; 124 | enum : int { EXTERNAL_I2S = 0, INTERNAL_DAC = 1, INTERNAL_PDM = 2 }; 125 | enum : int { CODEC_NONE = 0, CODEC_WAV = 1, CODEC_MP3 = 2, CODEC_AAC = 4, CODEC_FLAC = 5}; 126 | typedef enum { LEFTCHANNEL=0, RIGHTCHANNEL=1 } SampleIndex; 127 | 128 | const uint8_t volumetable[22]={ 0, 1, 2, 3, 4 , 6 , 8, 10, 12, 14, 17, 129 | 20, 23, 27, 30 ,34, 38, 43 ,48, 52, 58, 64}; //22 elements 130 | 131 | 132 | 133 | File audiofile; // @suppress("Abstract class cannot be instantiated") 134 | WiFiClient client; // @suppress("Abstract class cannot be instantiated") 135 | WiFiClientSecure clientsecure; // @suppress("Abstract class cannot be instantiated") 136 | char chbuf[256]; 137 | char path[256]; 138 | int m_id3Size=0; // length id3 tag 139 | int m_LFcount; // Detection of end of header 140 | uint32_t m_sampleRate=16000; 141 | int m_bytesLeft=0; 142 | int m_writePtr=0; // ptr sampleBuffer 143 | int m_readPtr=0; // ptr sampleBuffer 144 | uint32_t m_bitRate=0; // current bitrate given fom decoder 145 | uint32_t m_avr_bitrate; // average bitrate, median computed by VBR 146 | int m_readbytes=0; // bytes read 147 | int m_metalen=0; // Number of bytes in metadata 148 | int8_t m_playlist_num = 0 ; // Nonzero for selection from playlist 149 | uint8_t m_inBuff[1600]; // inputBuffer 150 | uint16_t m_inBuffwindex=0; // write index 151 | uint16_t m_inBuffrindex=0; // read index 152 | const uint16_t m_inBuffsize=sizeof(m_inBuff); // size of inputBuffer 153 | uint8_t m_rev=0; // revision 154 | uint8_t m_BCLK=0; // Bit Clock 155 | uint8_t m_LRC=0; // Left/Right Clock 156 | uint8_t m_DOUT=0; // Data Out 157 | int8_t m_DIN=0; // Data In, can be negative if unused (I2S_PIN_NO_CHANGE is -1) 158 | uint8_t m_vol=64; // volume 159 | uint8_t m_bitsPerSample=16; // bitsPerSample 160 | uint8_t m_channels=2; 161 | uint8_t m_i2s_num= I2S_NUM_0; // I2S_NUM_0 or I2S_NUM_1 162 | int16_t m_buffValid; 163 | int16_t m_lastFrameEnd; 164 | int16_t m_outBuff[2048*2]; //[1152 * 2]; // Interleaved L/R 165 | int16_t m_validSamples = 0; 166 | int16_t m_curSample; 167 | int16_t m_Sample[2]; 168 | int16_t* m_leftSample; 169 | int16_t* m_rightSample; 170 | uint16_t m_datamode=0; // Statemaschine 171 | uint32_t m_metaint = 0; // Number of databytes between metadata 172 | uint32_t m_totalcount = 0; // Counter mp3 data 173 | uint32_t m_chunkcount = 0 ; // Counter for chunked transfer 174 | uint32_t m_t0; 175 | uint32_t m_metaCount=0; // Bytecounter between metadata 176 | uint32_t m_contentlength = 0; // Stores the length if the stream comes from fileserver 177 | uint32_t m_bytectr = 0; // count received data 178 | uint32_t m_bytesNotDecoded=0; // pictures or something else that comes with the stream 179 | String m_audioName=""; // the name of the file 180 | String m_playlist ; // The URL of the specified playlist 181 | String m_lastHost=""; // Store the last URL to a webstream 182 | String m_metaline ; // Readable line in metadata 183 | String m_icyname ; // Icecast station name 184 | String m_st_remember=""; // Save the last streamtitle 185 | String m_icyurl=""; // Store ie icy-url if received 186 | String m_plsURL; 187 | String m_plsStationName; 188 | String m_icystreamtitle ; // Streamtitle from metadata 189 | bool m_f_unsync = false; 190 | bool m_f_exthdr = false; // ID3 extended header 191 | bool m_f_localfile = false ; // Play from local mp3-file 192 | bool m_f_webstream = false ; // Play from URL 193 | bool m_f_ssl=false; 194 | bool m_f_running=false; 195 | bool m_f_firststream_ready=false; // Set after connecttohost and first streamdata are available 196 | bool m_f_ctseen=false; // First line of header seen or not 197 | bool m_f_chunked = false ; // Station provides chunked transfer 198 | bool m_f_filled; // outputBuffer 199 | bool m_f_swm=false; 200 | bool m_f_firstmetabyte=false; // True if first metabyte (counter) 201 | bool m_f_plsFile=false; // Set if URL is known 202 | bool m_f_plsTitle=false; // Set if StationName is known 203 | bool m_ctseen=false; // First line of header seen or not 204 | bool m_f_stream=false; // Set false if stream is lost 205 | uint8_t m_codec = CODEC_NONE; // 206 | bool m_f_playing = false; // valid mp3 stream recognized 207 | bool m_f_webfile= false; // assume it's a radiostream, not a podcast 208 | size_t m_i2s_bytesWritten=0; // set in i2s_write() but not used 209 | uint32_t m_audioFileDuration=0; 210 | float m_audioCurrentTime=0; 211 | }; 212 | 213 | #endif /* AUDIO_H_ */ 214 | -------------------------------------------------------------------------------- /old-src/esp32_mp3/ESP32-audioI2S/src/aac_decoder/aac_decoder.h: -------------------------------------------------------------------------------- 1 | // based om helix aac decoder 2 | #pragma once 3 | #pragma GCC optimize ("O3") 4 | 5 | #include "Arduino.h" 6 | 7 | #define ASSERT(x) /* do nothing */ 8 | 9 | #ifndef MAX 10 | #define MAX(a,b) ((a) > (b) ? (a) : (b)) 11 | #endif 12 | 13 | #ifndef MIN 14 | #define MIN(a,b) ((a) < (b) ? (a) : (b)) 15 | #endif 16 | 17 | 18 | /* AAC file format */ 19 | enum { 20 | AAC_FF_Unknown = 0, /* should be 0 on init */ 21 | AAC_FF_ADTS = 1, 22 | AAC_FF_ADIF = 2, 23 | AAC_FF_RAW = 3 24 | }; 25 | 26 | /* syntactic element type */ 27 | enum { 28 | AAC_ID_INVALID = -1, 29 | AAC_ID_SCE = 0, 30 | AAC_ID_CPE = 1, 31 | AAC_ID_CCE = 2, 32 | AAC_ID_LFE = 3, 33 | AAC_ID_DSE = 4, 34 | AAC_ID_PCE = 5, 35 | AAC_ID_FIL = 6, 36 | AAC_ID_END = 7 37 | }; 38 | 39 | enum { 40 | ERR_AAC_NONE = 0, 41 | ERR_AAC_INDATA_UNDERFLOW = -1, 42 | ERR_AAC_NULL_POINTER = -2, 43 | ERR_AAC_INVALID_ADTS_HEADER = -3, 44 | ERR_AAC_INVALID_ADIF_HEADER = -4, 45 | ERR_AAC_INVALID_FRAME = -5, 46 | ERR_AAC_MPEG4_UNSUPPORTED = -6, 47 | ERR_AAC_CHANNEL_MAP = -7, 48 | ERR_AAC_SYNTAX_ELEMENT = -8, 49 | ERR_AAC_DEQUANT = -9, 50 | ERR_AAC_STEREO_PROCESS = -10, 51 | ERR_AAC_PNS = -11, 52 | ERR_AAC_SHORT_BLOCK_DEINT = -12, 53 | ERR_AAC_TNS = -13, 54 | ERR_AAC_IMDCT = -14, 55 | ERR_AAC_NCHANS_TOO_HIGH = -15, 56 | ERR_AAC_RAWBLOCK_PARAMS = -22, 57 | ERR_AAC_UNKNOWN = -9999 58 | }; 59 | 60 | typedef struct _AACDecInfo_t { 61 | int fillExtType; 62 | int prevBlockID; /* block information */ 63 | int currBlockID; 64 | int currInstTag; 65 | int sbDeinterleaveReqd[2]; // [MAX_NCHANS_ELEM] 66 | int adtsBlocksLeft; 67 | int bitRate; /* user-accessible info */ 68 | int nChans; 69 | int sampRate; 70 | int profile; 71 | int format; 72 | int sbrEnabled; 73 | int tnsUsed; 74 | int pnsUsed; 75 | int frameCount; 76 | } AACDecInfo_t; 77 | 78 | 79 | typedef struct _aac_BitStreamInfo_t { 80 | uint8_t *bytePtr; 81 | uint32_t iCache; 82 | int cachedBits; 83 | int nBytes; 84 | } aac_BitStreamInfo_t; 85 | 86 | typedef union _U64 { 87 | int64_t w64; 88 | struct { 89 | uint32_t lo32; 90 | int32_t hi32; 91 | } r; 92 | } U64; 93 | 94 | typedef struct _AACFrameInfo_t { 95 | int bitRate; 96 | int nChans; 97 | int sampRateCore; 98 | int sampRateOut; 99 | int bitsPerSample; 100 | int outputSamps; 101 | int profile; 102 | int tnsUsed; 103 | int pnsUsed; 104 | } AACFrameInfo_t; 105 | 106 | typedef struct _HuffInfo_t { 107 | int maxBits; /* number of bits in longest codeword */ 108 | uint8_t count[20]; /* count[MAX_HUFF_BITS] = number of codes with length i+1 bits */ 109 | int offset; /* offset into symbol table */ 110 | } HuffInfo_t; 111 | 112 | typedef struct _PulseInfo_t { 113 | uint8_t pulseDataPresent; 114 | uint8_t numPulse; 115 | uint8_t startSFB; 116 | uint8_t offset[4]; // [MAX_PULSES] 117 | uint8_t amp[4]; // [MAX_PULSES] 118 | } PulseInfo_t; 119 | 120 | typedef struct _TNSInfo_t { 121 | uint8_t tnsDataPresent; 122 | uint8_t numFilt[8]; // [MAX_TNS_FILTERS] max 1 filter each for 8 short windows, or 3 filters for 1 long window 123 | uint8_t coefRes[8]; // [MAX_TNS_FILTERS] 124 | uint8_t length[8]; // [MAX_TNS_FILTERS] 125 | uint8_t order[8]; // [MAX_TNS_FILTERS] 126 | uint8_t dir[8]; // [MAX_TNS_FILTERS] 127 | int8_t coef[60]; // [MAX_TNS_COEFS] max 3 filters * 20 coefs for 1 long window, or 1 filter * 7 coefs for each of 8 short windows 128 | } TNSInfo_t; 129 | 130 | typedef struct _GainControlInfo_t { 131 | uint8_t gainControlDataPresent; 132 | uint8_t maxBand; 133 | uint8_t adjNum[3][8]; // [MAX_GAIN_BANDS][MAX_GAIN_WIN] 134 | uint8_t alevCode[3][8][7]; // [MAX_GAIN_BANDS][MAX_GAIN_WIN][MAX_GAIN_ADJUST] 135 | uint8_t alocCode[3][8][7]; // [MAX_GAIN_BANDS][MAX_GAIN_WIN][MAX_GAIN_ADJUST] 136 | } GainControlInfo_t; 137 | 138 | typedef struct _ICSInfo_t { 139 | uint8_t icsResBit; 140 | uint8_t winSequence; 141 | uint8_t winShape; 142 | uint8_t maxSFB; 143 | uint8_t sfGroup; 144 | uint8_t predictorDataPresent; 145 | uint8_t predictorReset; 146 | uint8_t predictorResetGroupNum; 147 | uint8_t predictionUsed[41]; // [MAX_PRED_SFB] 148 | uint8_t numWinGroup; 149 | uint8_t winGroupLen[8]; // [MAX_WIN_GROUPS] 150 | } ICSInfo_t; 151 | 152 | typedef struct _ADTSHeader_t { 153 | /* fixed */ 154 | uint8_t id; /* MPEG bit - should be 1 */ 155 | uint8_t layer; /* MPEG layer - should be 0 */ 156 | uint8_t protectBit; /* 0 = CRC word follows, 1 = no CRC word */ 157 | uint8_t profile; /* 0 = main, 1 = LC, 2 = SSR, 3 = reserved */ 158 | uint8_t sampRateIdx; /* sample rate index range = [0, 11] */ 159 | uint8_t privateBit; /* ignore */ 160 | uint8_t channelConfig; /* 0 = implicit, >0 = use default table */ 161 | uint8_t origCopy; /* 0 = copy, 1 = original */ 162 | uint8_t home; /* ignore */ 163 | /* variable */ 164 | uint8_t copyBit; /* 1 bit of the 72-bit copyright ID (transmitted as 1 bit per frame) */ 165 | uint8_t copyStart; /* 1 = this bit starts the 72-bit ID, 0 = it does not */ 166 | int frameLength; /* length of frame */ 167 | int bufferFull; /* number of 32-bit words left in enc buffer, 0x7FF = VBR */ 168 | uint8_t numRawDataBlocks; /* number of raw data blocks in frame */ 169 | /* CRC */ 170 | int crcCheckWord; /* 16-bit CRC check word (present if protectBit == 0) */ 171 | } ADTSHeader_t; 172 | 173 | typedef struct _ADIFHeader_t { 174 | uint8_t copyBit; /* 0 = no copyright ID, 1 = 72-bit copyright ID follows immediately */ 175 | uint8_t origCopy; /* 0 = copy, 1 = original */ 176 | uint8_t home; /* ignore */ 177 | uint8_t bsType; /* bitstream type: 0 = CBR, 1 = VBR */ 178 | int bitRate; /* bitRate: CBR = bits/sec, VBR = peak bits/frame, 0 = unknown */ 179 | uint8_t numPCE; /* number of program config elements (max = 16) */ 180 | int bufferFull; /* bits left in bit reservoir */ 181 | uint8_t copyID[9]; /* [ADIF_COPYID_SIZE] optional 72-bit copyright ID */ 182 | } ADIFHeader_t; 183 | 184 | /* sizeof(ProgConfigElement_t) = 82 bytes (if KEEP_PCE_COMMENTS not defined) */ 185 | typedef struct _ProgConfigElement_t { 186 | uint8_t elemInstTag; /* element instance tag */ 187 | uint8_t profile; /* 0 = main, 1 = LC, 2 = SSR, 3 = reserved */ 188 | uint8_t sampRateIdx; /* sample rate index range = [0, 11] */ 189 | uint8_t numFCE; /* number of front channel elements (max = 15) */ 190 | uint8_t numSCE; /* number of side channel elements (max = 15) */ 191 | uint8_t numBCE; /* number of back channel elements (max = 15) */ 192 | uint8_t numLCE; /* number of LFE channel elements (max = 3) */ 193 | uint8_t numADE; /* number of associated data elements (max = 7) */ 194 | uint8_t numCCE; /* number of valid channel coupling elements (max = 15) */ 195 | uint8_t monoMixdown; /* mono mixdown: bit 4 = present flag, bits 3-0 = element number */ 196 | uint8_t stereoMixdown; /* stereo mixdown: bit 4 = present flag, bits 3-0 = element number */ 197 | uint8_t matrixMixdown; /* bit 4 = present flag, bit 3 = unused,bits 2-1 = index, bit 0 = pseudo-surround enable */ 198 | uint8_t fce[15]; /* [MAX_NUM_FCE] front element channel pair: bit 4 = SCE/CPE flag, bits 3-0 = inst tag */ 199 | uint8_t sce[15]; /* [MAX_NUM_SCE] side element channel pair: bit 4 = SCE/CPE flag, bits 3-0 = inst tag */ 200 | uint8_t bce[15]; /* [MAX_NUM_BCE] back element channel pair: bit 4 = SCE/CPE flag, bits 3-0 = inst tag */ 201 | uint8_t lce[3]; /* [MAX_NUM_LCE] instance tag for LFE elements */ 202 | uint8_t ade[7]; /* [MAX_NUM_ADE] instance tag for ADE elements */ 203 | uint8_t cce[15]; /* [MAX_NUM_BCE] channel coupling elements: bit 4 = switching flag, bits 3-0 = inst tag */ 204 | } ProgConfigElement_t; 205 | 206 | /* state info struct for baseline (MPEG-4 LC) decoding */ 207 | typedef struct _PSInfoBase_t { 208 | int dataCount; 209 | uint8_t dataBuf[510]; // [DATA_BUF_SIZE] 210 | /* state information which is the same throughout whole frame */ 211 | int nChans; 212 | int useImpChanMap; 213 | int sampRateIdx; 214 | /* state information which can be overwritten by subsequent elements within frame */ 215 | ICSInfo_t icsInfo[2]; // [MAX_NCHANS_ELEM] 216 | int commonWin; 217 | short scaleFactors[2][15*8]; // [MAX_NCHANS_ELEM][MAX_SF_BANDS] 218 | uint8_t sfbCodeBook[2][15*8]; // [MAX_NCHANS_ELEM][MAX_SF_BANDS] 219 | int msMaskPresent; 220 | uint8_t msMaskBits[(15 * 8 + 7) >> 3]; // [MAX_MS_MASK_BYTES] 221 | int pnsUsed[2]; // [MAX_NCHANS_ELEM] 222 | int pnsLastVal; 223 | int intensityUsed[2]; // [MAX_NCHANS_ELEM] 224 | // PulseInfo_t pulseInfo[2]; // [MAX_NCHANS_ELEM] 225 | TNSInfo_t tnsInfo[2]; // [MAX_NCHANS_ELEM] 226 | int tnsLPCBuf[20]; // [MAX_TNS_ORDER] 227 | int tnsWorkBuf[20]; //[MAX_TNS_ORDER] 228 | GainControlInfo_t gainControlInfo[2]; // [MAX_NCHANS_ELEM] 229 | int gbCurrent[2]; // [MAX_NCHANS_ELEM] 230 | int coef[2][1024]; // [MAX_NCHANS_ELEM][AAC_MAX_NSAMPS] 231 | /* state information which must be saved for each element and used in next frame */ 232 | int overlap[2][1024]; // [AAC_MAX_NCHANS][AAC_MAX_NSAMPS] 233 | int prevWinShape[2]; // [AAC_MAX_NCHANS] 234 | } PSInfoBase_t; 235 | 236 | bool AACDecoder_AllocateBuffers(void); 237 | void AACDecoder_FreeBuffers(void); 238 | int AACFindSyncWord(uint8_t *buf, int nBytes); 239 | void AACGetLastFrameInfo(AACFrameInfo_t *aacFrameInfo); 240 | int AACDecode(uint8_t *inbuf, int *bytesLeft, short *outbuf); 241 | int AACGetSampRate(); 242 | int AACGetChannels(); 243 | int AACGetBitsPerSample(); 244 | int AACGetBitrate(); 245 | int AACGetOutputSamps(); 246 | int AACGetBitrate(); 247 | void DecodeLPCCoefs(int order, int res, int8_t *filtCoef, int *a, int *b); 248 | int FilterRegion(int size, int dir, int order, int *audioCoef, int *a, int *hist); 249 | int TNSFilter(int ch); 250 | int DecodeSingleChannelElement(); 251 | int DecodeChannelPairElement(); 252 | int DecodeLFEChannelElement(); 253 | int DecodeDataStreamElement(); 254 | int DecodeProgramConfigElement(uint8_t idx); 255 | int DecodeFillElement(); 256 | int DecodeNextElement(uint8_t **buf, int *bitOffset, int *bitsAvail); 257 | void PreMultiply(int tabidx, int *zbuf1); 258 | void PostMultiply(int tabidx, int *fft1); 259 | void PreMultiplyRescale(int tabidx, int *zbuf1, int es); 260 | void PostMultiplyRescale(int tabidx, int *fft1, int es); 261 | void DCT4(int tabidx, int *coef, int gb); 262 | void BitReverse(int *inout, int tabidx); 263 | void R4FirstPass(int *x, int bg); 264 | void R8FirstPass(int *x, int bg); 265 | void R4Core(int *x, int bg, int gp, int *wtab); 266 | void R4FFT(int tabidx, int *x); 267 | void UnpackZeros(int nVals, int *coef); 268 | void UnpackQuads(int cb, int nVals, int *coef); 269 | void UnpackPairsNoEsc(int cb, int nVals, int *coef); 270 | void UnpackPairsEsc(int cb, int nVals, int *coef); 271 | void DecodeSpectrumLong(int ch); 272 | void DecodeSpectrumShort(int ch); 273 | void DecWindowOverlap(int *buf0, int *over0, short *pcm0, int nChans, int winTypeCurr, int winTypePrev); 274 | void DecWindowOverlapLongStart(int *buf0, int *over0, short *pcm0, int nChans, int winTypeCurr, int winTypePrev); 275 | void DecWindowOverlapLongStop(int *buf0, int *over0, short *pcm0, int nChans, int winTypeCurr, int winTypePrev); 276 | void DecWindowOverlapShort(int *buf0, int *over0, short *pcm0, int nChans, int winTypeCurr, int winTypePrev); 277 | int IMDCT(int ch, int chOut, short *outbuf); 278 | void DecodeICSInfo(ICSInfo_t *icsInfo, int sampRateIdx); 279 | void DecodeSectionData(int winSequence, int numWinGrp, int maxSFB, uint8_t *sfbCodeBook); 280 | int DecodeOneScaleFactor(); 281 | void DecodeScaleFactors(int numWinGrp, int maxSFB, int globalGain, uint8_t *sfbCodeBook, short *scaleFactors); 282 | void DecodePulseInfo(uint8_t ch); 283 | void DecodeTNSInfo(int winSequence, TNSInfo_t *ti, int8_t *tnsCoef); 284 | void DecodeGainControlInfo(int winSequence, GainControlInfo_t *gi); 285 | void DecodeICS(int ch); 286 | int DecodeNoiselessData(uint8_t **buf, int *bitOffset, int *bitsAvail, int ch); 287 | int DecodeHuffmanScalar(const signed short *huffTab, const HuffInfo_t *huffTabInfo, uint32_t bitBuf, int32_t *val); 288 | int UnpackADTSHeader(uint8_t **buf, int *bitOffset, int *bitsAvail); 289 | int GetADTSChannelMapping(uint8_t *buf, int bitOffset, int bitsAvail); 290 | int GetNumChannelsADIF(int nPCE); 291 | int GetSampleRateIdxADIF(int nPCE); 292 | int UnpackADIFHeader(uint8_t **buf, int *bitOffset, int *bitsAvail); 293 | int SetRawBlockParams(int copyLast, int nChans, int sampRate, int profile); 294 | int PrepareRawBlock(); 295 | int DequantBlock(int *inbuf, int nSamps, int scale); 296 | int AACDequantize(int ch); 297 | int DeinterleaveShortBlocks(int ch); 298 | uint32_t Get32BitVal(uint32_t *last); 299 | int InvRootR(int r); 300 | int ScaleNoiseVector(int *coef, int nVals, int sf); 301 | void GenerateNoiseVector(int *coef, int *last, int nVals); 302 | void CopyNoiseVector(int *coefL, int *coefR, int nVals); 303 | int PNS(int ch); 304 | int GetSampRateIdx(int sampRate); 305 | void StereoProcessGroup(int *coefL, int *coefR, const uint16_t *sfbTab, int msMaskPres, uint8_t *msMaskPtr, 306 | int msMaskOffset, int maxSFB, uint8_t *cbRight, short *sfRight, int *gbCurrent); 307 | int StereoProcess(); 308 | int RatioPowInv(int a, int b, int c); 309 | int SqrtFix(int q, int fBitsIn, int *fBitsOut); 310 | int InvRNormalized(int r); 311 | void BitReverse32(int *inout); 312 | void R8FirstPass32(int *r0); 313 | void R4Core32(int *r0); 314 | void FFT32C(int *x); 315 | void CVKernel1(int *XBuf, int *accBuf); 316 | void CVKernel2(int *XBuf, int *accBuf); 317 | void SetBitstreamPointer(int nBytes, uint8_t *buf); 318 | inline void RefillBitstreamCache(); 319 | uint32_t GetBits(int nBits); 320 | uint32_t GetBitsNoAdvance(int nBits); 321 | void AdvanceBitstream(int nBits); 322 | int CalcBitsUsed(uint8_t *startBuf, int startOffset); 323 | void ByteAlignBitstream(); 324 | 325 | -------------------------------------------------------------------------------- /old-src/esp32_mp3/ESP32-audioI2S/src/mp3_decoder/mp3_decoder.h: -------------------------------------------------------------------------------- 1 | // based om helix mp3 decoder 2 | #pragma once 3 | #pragma GCC optimize ("O3") 4 | 5 | #include "Arduino.h" 6 | #include "assert.h" 7 | 8 | static const uint8_t m_HUFF_PAIRTABS =32; 9 | static const uint8_t m_BLOCK_SIZE =18; 10 | static const uint8_t m_NBANDS =32; 11 | static const uint8_t m_MAX_REORDER_SAMPS =(192-126)*3; // largest critical band for short blocks (see sfBandTable) 12 | static const uint16_t m_VBUF_LENGTH =17*2* m_NBANDS; // for double-sized vbuf FIFO 13 | static const uint8_t m_MAX_SCFBD =4; // max scalefactor bands per channel 14 | static const uint16_t m_MAINBUF_SIZE =1940; 15 | static const uint8_t m_MAX_NGRAN =2; // max granules 16 | static const uint8_t m_MAX_NCHAN =2; // max channels 17 | static const uint16_t m_MAX_NSAMP =576; // max samples per channel, per granule 18 | 19 | enum { 20 | ERR_MP3_NONE = 0, 21 | ERR_MP3_INDATA_UNDERFLOW = -1, 22 | ERR_MP3_MAINDATA_UNDERFLOW = -2, 23 | ERR_MP3_FREE_BITRATE_SYNC = -3, 24 | ERR_MP3_OUT_OF_MEMORY = -4, 25 | ERR_MP3_NULL_POINTER = -5, 26 | ERR_MP3_INVALID_FRAMEHEADER = -6, 27 | ERR_MP3_INVALID_SIDEINFO = -7, 28 | ERR_MP3_INVALID_SCALEFACT = -8, 29 | ERR_MP3_INVALID_HUFFCODES = -9, 30 | ERR_MP3_INVALID_DEQUANTIZE = -10, 31 | ERR_MP3_INVALID_IMDCT = -11, 32 | ERR_MP3_INVALID_SUBBAND = -12, 33 | 34 | ERR_UNKNOWN = -9999 35 | }; 36 | 37 | typedef struct MP3FrameInfo { 38 | int bitrate; 39 | int nChans; 40 | int samprate; 41 | int bitsPerSample; 42 | int outputSamps; 43 | int layer; 44 | int version; 45 | } MP3FrameInfo_t; 46 | 47 | typedef struct SFBandTable { 48 | int/*short*/ l[23]; 49 | int/*short*/ s[14]; 50 | } SFBandTable_t; 51 | 52 | typedef struct BitStreamInfo { 53 | unsigned char *bytePtr; 54 | unsigned int iCache; 55 | int cachedBits; 56 | int nBytes; 57 | } BitStreamInfo_t; 58 | 59 | typedef enum { /* map these to the corresponding 2-bit values in the frame header */ 60 | Stereo = 0x00, /* two independent channels, but L and R frames might have different # of bits */ 61 | Joint = 0x01, /* coupled channels - layer III: mix of M-S and intensity, Layers I/II: intensity and direct coding only */ 62 | Dual = 0x02, /* two independent channels, L and R always have exactly 1/2 the total bitrate */ 63 | Mono = 0x03 /* one channel */ 64 | } StereoMode_t; 65 | 66 | typedef enum { /* map to 0,1,2 to make table indexing easier */ 67 | MPEG1 = 0, 68 | MPEG2 = 1, 69 | MPEG25 = 2 70 | } MPEGVersion_t; 71 | 72 | typedef struct FrameHeader { 73 | int layer; /* layer index (1, 2, or 3) */ 74 | int crc; /* CRC flag: 0 = disabled, 1 = enabled */ 75 | int brIdx; /* bitrate index (0 - 15) */ 76 | int srIdx; /* sample rate index (0 - 2) */ 77 | int paddingBit; /* padding flag: 0 = no padding, 1 = single pad byte */ 78 | int privateBit; /* unused */ 79 | int modeExt; /* used to decipher joint stereo mode */ 80 | int copyFlag; /* copyright flag: 0 = no, 1 = yes */ 81 | int origFlag; /* original flag: 0 = copy, 1 = original */ 82 | int emphasis; /* deemphasis mode */ 83 | int CRCWord; /* CRC word (16 bits, 0 if crc not enabled) */ 84 | } FrameHeader_t; 85 | 86 | typedef struct SideInfoSub { 87 | int part23Length; /* number of bits in main data */ 88 | int nBigvals; /* 2x this = first set of Huffman cw's (maximum amplitude can be > 1) */ 89 | int globalGain; /* overall gain for dequantizer */ 90 | int sfCompress; /* unpacked to figure out number of bits in scale factors */ 91 | int winSwitchFlag; /* window switching flag */ 92 | int blockType; /* block type */ 93 | int mixedBlock; /* 0 = regular block (all short or long), 1 = mixed block */ 94 | int tableSelect[3]; /* index of Huffman tables for the big values regions */ 95 | int subBlockGain[3]; /* subblock gain offset, relative to global gain */ 96 | int region0Count; /* 1+region0Count = num scale factor bands in first region of bigvals */ 97 | int region1Count; /* 1+region1Count = num scale factor bands in second region of bigvals */ 98 | int preFlag; /* for optional high frequency boost */ 99 | int sfactScale; /* scaling of the scalefactors */ 100 | int count1TableSelect; /* index of Huffman table for quad codewords */ 101 | } SideInfoSub_t; 102 | 103 | typedef struct SideInfo { 104 | int mainDataBegin; 105 | int privateBits; 106 | int scfsi[m_MAX_NCHAN][m_MAX_SCFBD]; /* 4 scalefactor bands per channel */ 107 | } SideInfo_t; 108 | 109 | typedef struct { 110 | int cbType; /* pure long = 0, pure short = 1, mixed = 2 */ 111 | int cbEndS[3]; /* number nonzero short cb's, per subbblock */ 112 | int cbEndSMax; /* max of cbEndS[] */ 113 | int cbEndL; /* number nonzero long cb's */ 114 | } CriticalBandInfo_t; 115 | 116 | typedef struct DequantInfo { 117 | int workBuf[m_MAX_REORDER_SAMPS]; /* workbuf for reordering short blocks */ 118 | } DequantInfo_t; 119 | 120 | typedef struct HuffmanInfo { 121 | int huffDecBuf[m_MAX_NCHAN][m_MAX_NSAMP]; /* used both for decoded Huffman values and dequantized coefficients */ 122 | int nonZeroBound[m_MAX_NCHAN]; /* number of coeffs in huffDecBuf[ch] which can be > 0 */ 123 | int gb[m_MAX_NCHAN]; /* minimum number of guard bits in huffDecBuf[ch] */ 124 | } HuffmanInfo_t; 125 | 126 | typedef enum HuffTabType { 127 | noBits, 128 | oneShot, 129 | loopNoLinbits, 130 | loopLinbits, 131 | quadA, 132 | quadB, 133 | invalidTab 134 | } HuffTabType_t; 135 | 136 | typedef struct HuffTabLookup { 137 | int linBits; 138 | int tabType; /*HuffTabType*/ 139 | } HuffTabLookup_t; 140 | 141 | typedef struct IMDCTInfo { 142 | int outBuf[m_MAX_NCHAN][m_BLOCK_SIZE][m_NBANDS]; /* output of IMDCT */ 143 | int overBuf[m_MAX_NCHAN][m_MAX_NSAMP / 2]; /* overlap-add buffer (by symmetry, only need 1/2 size) */ 144 | int numPrevIMDCT[m_MAX_NCHAN]; /* how many IMDCT's calculated in this channel on prev. granule */ 145 | int prevType[m_MAX_NCHAN]; 146 | int prevWinSwitch[m_MAX_NCHAN]; 147 | int gb[m_MAX_NCHAN]; 148 | } IMDCTInfo_t; 149 | 150 | typedef struct BlockCount { 151 | int nBlocksLong; 152 | int nBlocksTotal; 153 | int nBlocksPrev; 154 | int prevType; 155 | int prevWinSwitch; 156 | int currWinSwitch; 157 | int gbIn; 158 | int gbOut; 159 | } BlockCount_t; 160 | 161 | typedef struct ScaleFactorInfoSub { /* max bits in scalefactors = 5, so use char's to save space */ 162 | char l[23]; /* [band] */ 163 | char s[13][3]; /* [band][window] */ 164 | } ScaleFactorInfoSub_t; 165 | 166 | typedef struct ScaleFactorJS { /* used in MPEG 2, 2.5 intensity (joint) stereo only */ 167 | int intensityScale; 168 | int slen[4]; 169 | int nr[4]; 170 | } ScaleFactorJS_t; 171 | 172 | /* NOTE - could get by with smaller vbuf if memory is more important than speed 173 | * (in Subband, instead of replicating each block in FDCT32 you would do a memmove on the 174 | * last 15 blocks to shift them down one, a hardware style FIFO) 175 | */ 176 | typedef struct SubbandInfo { 177 | int vbuf[m_MAX_NCHAN * m_VBUF_LENGTH]; /* vbuf for fast DCT-based synthesis PQMF - double size for speed (no modulo indexing) */ 178 | int vindex; /* internal index for tracking position in vbuf */ 179 | } SubbandInfo_t; 180 | 181 | typedef struct MP3DecInfo { 182 | /* buffer which must be large enough to hold largest possible main_data section */ 183 | unsigned char mainBuf[m_MAINBUF_SIZE]; 184 | /* special info for "free" bitrate files */ 185 | int freeBitrateFlag; 186 | int freeBitrateSlots; 187 | /* user-accessible info */ 188 | int bitrate; 189 | int nChans; 190 | int samprate; 191 | int nGrans; /* granules per frame */ 192 | int nGranSamps; /* samples per granule */ 193 | int nSlots; 194 | int layer; 195 | 196 | int mainDataBegin; 197 | int mainDataBytes; 198 | int part23Length[m_MAX_NGRAN][m_MAX_NCHAN]; 199 | } MP3DecInfo_t; 200 | 201 | 202 | 203 | 204 | /* format = Q31 205 | * #define M_PI 3.14159265358979323846 206 | * double u = 2.0 * M_PI / 9.0; 207 | * float c0 = sqrt(3.0) / 2.0; 208 | * float c1 = cos(u); 209 | * float c2 = cos(2*u); 210 | * float c3 = sin(u); 211 | * float c4 = sin(2*u); 212 | */ 213 | 214 | const int c9_0 = 0x6ed9eba1; 215 | const int c9_1 = 0x620dbe8b; 216 | const int c9_2 = 0x163a1a7e; 217 | const int c9_3 = 0x5246dd49; 218 | const int c9_4 = 0x7e0e2e32; 219 | 220 | 221 | 222 | const int c3_0 = 0x6ed9eba1; /* format = Q31, cos(pi/6) */ 223 | const int c6[3] = { 0x7ba3751d, 0x5a82799a, 0x2120fb83 }; /* format = Q31, cos(((0:2) + 0.5) * (pi/6)) */ 224 | 225 | /* format = Q31 226 | * cos(((0:8) + 0.5) * (pi/18)) 227 | */ 228 | const uint32_t c18[9] = { 0x7f834ed0, 0x7ba3751d, 0x7401e4c1, 0x68d9f964, 0x5a82799a, 0x496af3e2, 0x36185aee, 0x2120fb83, 0x0b27eb5c}; 229 | 230 | /* scale factor lengths (num bits) */ 231 | const char m_SFLenTab[16][2] = { {0, 0}, {0, 1}, {0, 2}, {0, 3}, {3, 0}, {1, 1}, {1, 2}, {1, 3}, 232 | {2, 1}, {2, 2}, {2, 3}, {3, 1}, {3, 2}, {3, 3}, {4, 2}, {4, 3}}; 233 | 234 | /* NRTab[size + 3*is_right][block type][partition] 235 | * block type index: 0 = (bt0,bt1,bt3), 1 = bt2 non-mixed, 2 = bt2 mixed 236 | * partition: scale factor groups (sfb1 through sfb4) 237 | * for block type = 2 (mixed or non-mixed) / by 3 is rolled into this table 238 | * (for 3 short blocks per long block) 239 | * see 2.4.3.2 in MPEG 2 (low sample rate) spec 240 | * stuff rolled into this table: 241 | * NRTab[x][1][y] --> (NRTab[x][1][y]) / 3 242 | * NRTab[x][2][>=1] --> (NRTab[x][2][>=1]) / 3 (first partition is long block) 243 | */ 244 | const char NRTab[6][3][4] = { 245 | {{ 6, 5, 5, 5}, {3, 3, 3, 3}, {6, 3, 3, 3}}, 246 | {{ 6, 5, 7, 3}, {3, 3, 4, 2}, {6, 3, 4, 2}}, 247 | {{11, 10, 0, 0}, {6, 6, 0, 0}, {6, 3, 6, 0}}, 248 | {{ 7, 7, 7, 0}, {4, 4, 4, 0}, {6, 5, 4, 0}}, 249 | {{ 6, 6, 6, 3}, {4, 3, 3, 2}, {6, 4, 3, 2}}, 250 | {{ 8, 8, 5, 0}, {5, 4, 3, 0}, {6, 6, 3, 0}} 251 | }; 252 | 253 | 254 | 255 | /* optional pre-emphasis for high-frequency scale factor bands */ 256 | const char preTab[22] = { 0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,2,2,3,3,3,2,0 }; 257 | 258 | /* pow(2,-i/4) for i=0..3, Q31 format */ 259 | const int pow14[4] PROGMEM = { 260 | 0x7fffffff, 0x6ba27e65, 0x5a82799a, 0x4c1bf829 261 | }; 262 | 263 | 264 | /* 265 | * Minimax polynomial approximation to pow(x, 4/3), over the range 266 | * poly43lo: x = [0.5, 0.7071] 267 | * poly43hi: x = [0.7071, 1.0] 268 | * 269 | * Relative error < 1E-7 270 | * Coefs are scaled by 4, 2, 1, 0.5, 0.25 271 | */ 272 | const unsigned int poly43lo[5] PROGMEM = { 0x29a0bda9, 0xb02e4828, 0x5957aa1b, 0x236c498d, 0xff581859 }; 273 | const unsigned int poly43hi[5] PROGMEM = { 0x10852163, 0xd333f6a4, 0x46e9408b, 0x27c2cef0, 0xfef577b4 }; 274 | 275 | /* pow(2, i*4/3) as exp and frac */ 276 | const int pow2exp[8] PROGMEM = { 14, 13, 11, 10, 9, 7, 6, 5 }; 277 | 278 | const int pow2frac[8] PROGMEM = { 279 | 0x6597fa94, 0x50a28be6, 0x7fffffff, 0x6597fa94, 280 | 0x50a28be6, 0x7fffffff, 0x6597fa94, 0x50a28be6 281 | }; 282 | 283 | const uint16_t m_HUFF_OFFSET_01= 0; 284 | const uint16_t m_HUFF_OFFSET_02= 9 + m_HUFF_OFFSET_01; 285 | const uint16_t m_HUFF_OFFSET_03= 65 + m_HUFF_OFFSET_02; 286 | const uint16_t m_HUFF_OFFSET_05= 65 + m_HUFF_OFFSET_03; 287 | const uint16_t m_HUFF_OFFSET_06=257 + m_HUFF_OFFSET_05; 288 | const uint16_t m_HUFF_OFFSET_07=129 + m_HUFF_OFFSET_06; 289 | const uint16_t m_HUFF_OFFSET_08=110 + m_HUFF_OFFSET_07; 290 | const uint16_t m_HUFF_OFFSET_09=280 + m_HUFF_OFFSET_08; 291 | const uint16_t m_HUFF_OFFSET_10= 93 + m_HUFF_OFFSET_09; 292 | const uint16_t m_HUFF_OFFSET_11=320 + m_HUFF_OFFSET_10; 293 | const uint16_t m_HUFF_OFFSET_12=296 + m_HUFF_OFFSET_11; 294 | const uint16_t m_HUFF_OFFSET_13=185 + m_HUFF_OFFSET_12; 295 | const uint16_t m_HUFF_OFFSET_15=497 + m_HUFF_OFFSET_13; 296 | const uint16_t m_HUFF_OFFSET_16=580 + m_HUFF_OFFSET_15; 297 | const uint16_t m_HUFF_OFFSET_24=651 + m_HUFF_OFFSET_16; 298 | 299 | const int huffTabOffset[m_HUFF_PAIRTABS] PROGMEM = { 300 | 0, m_HUFF_OFFSET_01, m_HUFF_OFFSET_02, m_HUFF_OFFSET_03, 301 | 0, m_HUFF_OFFSET_05, m_HUFF_OFFSET_06, m_HUFF_OFFSET_07, 302 | m_HUFF_OFFSET_08, m_HUFF_OFFSET_09, m_HUFF_OFFSET_10, m_HUFF_OFFSET_11, 303 | m_HUFF_OFFSET_12, m_HUFF_OFFSET_13, 0, m_HUFF_OFFSET_15, 304 | m_HUFF_OFFSET_16, m_HUFF_OFFSET_16, m_HUFF_OFFSET_16, m_HUFF_OFFSET_16, 305 | m_HUFF_OFFSET_16, m_HUFF_OFFSET_16, m_HUFF_OFFSET_16, m_HUFF_OFFSET_16, 306 | m_HUFF_OFFSET_24, m_HUFF_OFFSET_24, m_HUFF_OFFSET_24, m_HUFF_OFFSET_24, 307 | m_HUFF_OFFSET_24, m_HUFF_OFFSET_24, m_HUFF_OFFSET_24, m_HUFF_OFFSET_24,}; 308 | 309 | const HuffTabLookup_t huffTabLookup[m_HUFF_PAIRTABS] PROGMEM = { 310 | { 0, noBits }, 311 | { 0, oneShot }, 312 | { 0, oneShot }, 313 | { 0, oneShot }, 314 | { 0, invalidTab }, 315 | { 0, oneShot }, 316 | { 0, oneShot }, 317 | { 0, loopNoLinbits }, 318 | { 0, loopNoLinbits }, 319 | { 0, loopNoLinbits }, 320 | { 0, loopNoLinbits }, 321 | { 0, loopNoLinbits }, 322 | { 0, loopNoLinbits }, 323 | { 0, loopNoLinbits }, 324 | { 0, invalidTab }, 325 | { 0, loopNoLinbits }, 326 | { 1, loopLinbits }, 327 | { 2, loopLinbits }, 328 | { 3, loopLinbits }, 329 | { 4, loopLinbits }, 330 | { 6, loopLinbits }, 331 | { 8, loopLinbits }, 332 | { 10, loopLinbits }, 333 | { 13, loopLinbits }, 334 | { 4, loopLinbits }, 335 | { 5, loopLinbits }, 336 | { 6, loopLinbits }, 337 | { 7, loopLinbits }, 338 | { 8, loopLinbits }, 339 | { 9, loopLinbits }, 340 | { 11, loopLinbits }, 341 | { 13, loopLinbits }, 342 | }; 343 | 344 | 345 | const int quadTabOffset[2] PROGMEM = {0, 64}; 346 | const int quadTabMaxBits[2] PROGMEM = {6, 4}; 347 | 348 | /* indexing = [version][samplerate index] 349 | * sample rate of frame (Hz) 350 | */ 351 | const int samplerateTab[3][3] PROGMEM = { 352 | { 44100, 48000, 32000 }, /* MPEG-1 */ 353 | { 22050, 24000, 16000 }, /* MPEG-2 */ 354 | { 11025, 12000, 8000 }, /* MPEG-2.5 */ 355 | }; 356 | 357 | 358 | 359 | /* indexing = [version][layer] 360 | * number of samples in one frame (per channel) 361 | */ 362 | const int/*short*/samplesPerFrameTab[3][3] PROGMEM = { { 384, 1152, 1152 }, /* MPEG1 */ 363 | { 384, 1152, 576 }, /* MPEG2 */ 364 | { 384, 1152, 576 }, /* MPEG2.5 */ 365 | }; 366 | 367 | /* layers 1, 2, 3 */ 368 | const short bitsPerSlotTab[3] = { 32, 8, 8 }; 369 | 370 | /* indexing = [version][mono/stereo] 371 | * number of bytes in side info section of bitstream 372 | */ 373 | const int/*short*/sideBytesTab[3][2] PROGMEM = { { 17, 32 }, /* MPEG-1: mono, stereo */ 374 | { 9, 17 }, /* MPEG-2: mono, stereo */ 375 | { 9, 17 }, /* MPEG-2.5: mono, stereo */ 376 | }; 377 | 378 | /* indexing = [version][sampleRate][long (.l) or short (.s) block] 379 | * sfBandTable[v][s].l[cb] = index of first bin in critical band cb (long blocks) 380 | * sfBandTable[v][s].s[cb] = index of first bin in critical band cb (short blocks) 381 | */ 382 | const SFBandTable_t sfBandTable[3][3] PROGMEM = { 383 | { /* MPEG-1 (44, 48, 32 kHz) */ 384 | { {0, 4, 8, 12, 16, 20, 24, 30, 36, 44, 52, 62, 74, 90, 110, 134, 162, 196, 238, 288, 342, 418, 576 }, 385 | {0, 4, 8, 12, 16, 22, 30, 40, 52, 66, 84, 106, 136, 192} }, 386 | { {0, 4, 8, 12, 16, 20, 24, 30, 36, 42, 50, 60, 72, 88, 106, 128, 156, 190, 230, 276, 330, 384, 576 }, 387 | {0, 4, 8, 12, 16, 22, 28, 38, 50, 64, 80, 100, 126, 192} }, 388 | { {0, 4, 8, 12, 16, 20, 24, 30, 36, 44, 54, 66, 82, 102, 126, 156, 194, 240, 296, 364, 448, 550, 576 }, 389 | {0, 4, 8, 12, 16, 22, 30, 42, 58, 78, 104, 138, 180, 192} } }, 390 | { /* MPEG-2 (22, 24, 16 kHz) */ 391 | { {0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96, 116, 140, 168, 200, 238, 284, 336, 396, 464, 522, 576 }, 392 | {0, 4, 8, 12, 18, 24, 32, 42, 56, 74, 100, 132, 174, 192} }, 393 | { {0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96, 114, 136, 162, 194, 232, 278, 332, 394, 464, 540, 576 }, 394 | {0, 4, 8, 12, 18, 26, 36, 48, 62, 80, 104, 136, 180, 192} }, 395 | { {0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96, 116, 140, 168, 200, 238, 284, 336, 396, 464, 522, 576 }, 396 | {0, 4, 8, 12, 18, 26, 36, 48, 62, 80, 104, 134, 174, 192} }, }, 397 | { /* MPEG-2.5 (11, 12, 8 kHz) */ 398 | { {0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96, 116, 140, 168, 200, 238, 284, 336, 396, 464, 522, 576 }, 399 | {0, 4, 8, 12, 18, 26, 36, 48, 62, 80, 104, 134, 174, 192 } }, 400 | { {0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96, 116, 140, 168, 200, 238, 284, 336, 396, 464, 522, 576 }, 401 | {0, 4, 8, 12, 18, 26, 36, 48, 62, 80, 104, 134, 174, 192 } }, 402 | { {0, 12, 24, 36, 48, 60, 72, 88, 108, 132, 160, 192, 232, 280, 336, 400, 476, 566, 568, 570, 572, 574, 576 }, 403 | {0, 8, 16, 24, 36, 52, 72, 96, 124, 160, 162, 164, 166, 192 } }, }, 404 | }; 405 | 406 | 407 | /* indexing = [intensity scale on/off][left/right] 408 | * format = Q30, range = [0.0, 1.414] 409 | * 410 | * illegal intensity position scalefactors (see comments on ISFMpeg1) 411 | */ 412 | const int ISFIIP[2][2] PROGMEM = { 413 | {0x40000000, 0x00000000}, /* mid-side off */ 414 | {0x40000000, 0x40000000}, /* mid-side on */ 415 | }; 416 | 417 | const unsigned char uniqueIDTab[8] = {0x5f, 0x4b, 0x43, 0x5f, 0x5f, 0x4a, 0x52, 0x5f}; 418 | 419 | /* anti-alias coefficients - see spec Annex B, table 3-B.9 420 | * csa[0][i] = CSi, csa[1][i] = CAi 421 | * format = Q31 422 | */ 423 | const uint32_t csa[8][2] PROGMEM = { 424 | {0x6dc253f0, 0xbe2500aa}, 425 | {0x70dcebe4, 0xc39e4949}, 426 | {0x798d6e73, 0xd7e33f4a}, 427 | {0x7ddd40a7, 0xe8b71176}, 428 | {0x7f6d20b7, 0xf3e4fe2f}, 429 | {0x7fe47e40, 0xfac1a3c7}, 430 | {0x7ffcb263, 0xfe2ebdc6}, 431 | {0x7fffc694, 0xff86c25d}, 432 | }; 433 | 434 | /* format = Q30, right shifted by 12 (sign bits only in top 12 - undo this when rounding to short) 435 | * this is to enable early-terminating multiplies on ARM 436 | * range = [-1.144287109, 1.144989014] 437 | * max gain of filter (per output sample) ~= 2.731 438 | * 439 | * new (properly sign-flipped) values 440 | * - these actually are correct to 32 bits, (floating-pt coefficients in spec 441 | * chosen such that only ~20 bits are required) 442 | * 443 | * Reordering - see table 3-B.3 in spec (appendix B) 444 | * 445 | * polyCoef[i] = 446 | * D[ 0, 32, 64, ... 480], i = [ 0, 15] 447 | * D[ 1, 33, 65, ... 481], i = [ 16, 31] 448 | * D[ 2, 34, 66, ... 482], i = [ 32, 47] 449 | * ... 450 | * D[15, 47, 79, ... 495], i = [240,255] 451 | * 452 | * also exploits symmetry: D[i] = -D[512 - i], for i = [1, 255] 453 | * 454 | * polyCoef[256, 257, ... 263] are for special case of sample 16 (out of 0) 455 | * see PolyphaseStereo() and PolyphaseMono() 456 | */ 457 | 458 | // prototypes 459 | bool MP3Decoder_AllocateBuffers(void); 460 | void MP3Decoder_FreeBuffers(); 461 | int MP3Decode( unsigned char *inbuf, int *bytesLeft, short *outbuf, int useSize); 462 | void MP3GetLastFrameInfo(); 463 | int MP3GetNextFrameInfo(unsigned char *buf); 464 | int MP3FindSyncWord(unsigned char *buf, int nBytes); 465 | int MP3GetSampRate(); 466 | int MP3GetChannels(); 467 | int MP3GetBitsPerSample(); 468 | int MP3GetBitrate(); 469 | int MP3GetOutputSamps(); 470 | 471 | //internally used 472 | void MP3Decoder_ClearBuffer(void); 473 | void PolyphaseMono(short *pcm, int *vbuf, const uint32_t *coefBase); 474 | void PolyphaseStereo(short *pcm, int *vbuf, const uint32_t *coefBase); 475 | void SetBitstreamPointer(BitStreamInfo_t *bsi, int nBytes, unsigned char *buf); 476 | unsigned int GetBits(BitStreamInfo_t *bsi, int nBits); 477 | int CalcBitsUsed(BitStreamInfo_t *bsi, unsigned char *startBuf, int startOffset); 478 | int DequantChannel(int *sampleBuf, int *workBuf, int *nonZeroBound, SideInfoSub_t *sis, ScaleFactorInfoSub_t *sfis, CriticalBandInfo_t *cbi); 479 | void MidSideProc(int x[m_MAX_NCHAN][m_MAX_NSAMP], int nSamps, int mOut[2]); 480 | void IntensityProcMPEG1(int x[m_MAX_NCHAN][m_MAX_NSAMP], int nSamps, ScaleFactorInfoSub_t *sfis, CriticalBandInfo_t *cbi, int midSideFlag, int mixFlag, int mOut[2]); 481 | void IntensityProcMPEG2(int x[m_MAX_NCHAN][m_MAX_NSAMP], int nSamps, ScaleFactorInfoSub_t *sfis, CriticalBandInfo_t *cbi, ScaleFactorJS_t *sfjs, int midSideFlag, int mixFlag, int mOut[2]); 482 | void FDCT32(int *x, int *d, int offset, int oddBlock, int gb);// __attribute__ ((section (".data"))); 483 | void FreeBuffers(); 484 | int CheckPadBit(); 485 | int UnpackFrameHeader(unsigned char *buf); 486 | int UnpackSideInfo(unsigned char *buf); 487 | int DecodeHuffman( unsigned char *buf, int *bitOffset, int huffBlockBits, int gr, int ch); 488 | int MP3Dequantize( int gr); 489 | int IMDCT( int gr, int ch); 490 | int UnpackScaleFactors( unsigned char *buf, int *bitOffset, int bitsAvail, int gr, int ch); 491 | int Subband(short *pcmBuf); 492 | short ClipToShort(int x, int fracBits); 493 | void RefillBitstreamCache(BitStreamInfo_t *bsi); 494 | void UnpackSFMPEG1(BitStreamInfo_t *bsi, SideInfoSub_t *sis, ScaleFactorInfoSub_t *sfis, int *scfsi, int gr, ScaleFactorInfoSub_t *sfisGr0); 495 | void UnpackSFMPEG2(BitStreamInfo_t *bsi, SideInfoSub_t *sis, ScaleFactorInfoSub_t *sfis, int gr, int ch, int modeExt, ScaleFactorJS_t *sfjs); 496 | int MP3FindFreeSync(unsigned char *buf, unsigned char firstFH[4], int nBytes); 497 | void MP3ClearBadFrame( short *outbuf); 498 | int DecodeHuffmanPairs(int *xy, int nVals, int tabIdx, int bitsLeft, unsigned char *buf, int bitOffset); 499 | int DecodeHuffmanQuads(int *vwxy, int nVals, int tabIdx, int bitsLeft, unsigned char *buf, int bitOffset); 500 | int DequantBlock(int *inbuf, int *outbuf, int num, int scale); 501 | void AntiAlias(int *x, int nBfly); 502 | void WinPrevious(int *xPrev, int *xPrevWin, int btPrev); 503 | int FreqInvertRescale(int *y, int *xPrev, int blockIdx, int es); 504 | void idct9(int *x); 505 | int IMDCT36(int *xCurr, int *xPrev, int *y, int btCurr, int btPrev, int blockIdx, int gb); 506 | void imdct12(int *x, int *out); 507 | int IMDCT12x3(int *xCurr, int *xPrev, int *y, int btPrev, int blockIdx, int gb); 508 | int HybridTransform(int *xCurr, int *xPrev, int y[m_BLOCK_SIZE][m_NBANDS], SideInfoSub_t *sis, BlockCount_t *bc); 509 | inline uint64_t SAR64(uint64_t x, int n) {return x >> n;} 510 | inline int MULSHIFT32(int x, int y) { int z; z = (uint64_t) x * (uint64_t) y >> 32; return z;} 511 | inline uint64_t MADD64(uint64_t sum64, int x, int y) {sum64 += (uint64_t) x * (uint64_t) y; return sum64;}/* returns 64-bit value in [edx:eax] */ 512 | inline int CLZ(int x){int numZeros; if (!x) return(sizeof(int) * 8); numZeros = 0; while (!(x & 0x80000000)){numZeros++; x <<= 1;} return numZeros;} 513 | inline uint64_t xSAR64(uint64_t x, int n){return x >> n;} 514 | inline int FASTABS(int x){ int sign; sign=x>>(sizeof(int)*8-1); x^=sign; x-=sign; return x;} 515 | 516 | 517 | -------------------------------------------------------------------------------- /old-src/esp32_mp3/esp32_mp3.ino: -------------------------------------------------------------------------------- 1 | #include "Arduino.h" 2 | #include "WiFiMulti.h" 3 | #include "Audio.h" 4 | #include "SPI.h" 5 | #include "SD.h" 6 | #include "FS.h" 7 | 8 | // Digital I/O used //Makerfabs Audio V2.0 9 | #define SD_CS 22 10 | #define SPI_MOSI 23 11 | #define SPI_MISO 19 12 | #define SPI_SCK 18 13 | 14 | #define I2S_DOUT 27 15 | #define I2S_BCLK 26 16 | #define I2S_LRC 25 17 | 18 | Audio audio; 19 | WiFiMulti wifiMulti; 20 | 21 | String ssid = "Makerfabs"; 22 | String password = "20160704"; 23 | 24 | void setup() { 25 | pinMode(SD_CS, OUTPUT); digitalWrite(SD_CS, HIGH); 26 | SPI.begin(SPI_SCK, SPI_MISO, SPI_MOSI); 27 | SPI.setFrequency(1000000); 28 | Serial.begin(115200); 29 | SD.begin(SD_CS); 30 | WiFi.mode(WIFI_STA); 31 | wifiMulti.addAP(ssid.c_str(), password.c_str()); 32 | wifiMulti.run(); 33 | if(WiFi.status() != WL_CONNECTED){ 34 | WiFi.disconnect(true); 35 | wifiMulti.run(); 36 | } 37 | audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT); 38 | audio.setVolume(21); // 0...21 39 | 40 | // audio.connecttoFS(SD, "/320k_test.mp3"); 41 | audio.connecttoFS(SD, "/MoonlightBay.mp3");//ChildhoodMemory.mp3 //MoonRiver.mp3 42 | // audio.connecttoFS(SD, "test.wav"); 43 | // audio.connecttohost("http://www.wdr.de/wdrlive/media/einslive.m3u"); 44 | // audio.connecttohost("http://macslons-irish-pub-radio.com/media.asx"); 45 | // audio.connecttohost("http://mp3.ffh.de/radioffh/hqlivestream.aac"); // 128k aac 46 | // audio.connecttohost("http://mp3.ffh.de/radioffh/hqlivestream.mp3"); // 128k mp3 47 | // audio.connecttospeech("Wenn die Hunde schlafen, kann der Wolf gut Schafe stehlen.", "de"); 48 | } 49 | 50 | void loop() 51 | { 52 | audio.loop(); 53 | if(Serial.available()){ // put streamURL in serial monitor 54 | audio.stopSong(); 55 | String r=Serial.readString(); r.trim(); 56 | if(r.length()>5) audio.connecttohost(r); 57 | log_i("free heap=%i", ESP.getFreeHeap()); 58 | } 59 | } 60 | 61 | // optional 62 | void audio_info(const char *info){ 63 | Serial.print("info "); Serial.println(info); 64 | } 65 | void audio_id3data(const char *info){ //id3 metadata 66 | Serial.print("id3data ");Serial.println(info); 67 | } 68 | void audio_eof_mp3(const char *info){ //end of file 69 | Serial.print("eof_mp3 ");Serial.println(info); 70 | } 71 | void audio_showstation(const char *info){ 72 | Serial.print("station ");Serial.println(info); 73 | } 74 | void audio_showstreaminfo(const char *info){ 75 | Serial.print("streaminfo ");Serial.println(info); 76 | } 77 | void audio_showstreamtitle(const char *info){ 78 | Serial.print("streamtitle ");Serial.println(info); 79 | } 80 | void audio_bitrate(const char *info){ 81 | Serial.print("bitrate ");Serial.println(info); 82 | } 83 | void audio_commercial(const char *info){ //duration in sec 84 | Serial.print("commercial ");Serial.println(info); 85 | } 86 | void audio_icyurl(const char *info){ //homepage 87 | Serial.print("icyurl ");Serial.println(info); 88 | } 89 | void audio_lasthost(const char *info){ //stream URL played 90 | Serial.print("lasthost ");Serial.println(info); 91 | } 92 | void audio_eof_speech(const char *info){ 93 | Serial.print("eof_speech ");Serial.println(info); 94 | } 95 | -------------------------------------------------------------------------------- /old-src/esp32_sdtest/esp32_sdtest.ino: -------------------------------------------------------------------------------- 1 | 2 | #include "FS.h" 3 | #include "SD.h" 4 | #include "SPI.h" 5 | 6 | void listDir(fs::FS &fs, const char * dirname, uint8_t levels){ 7 | Serial.printf("Listing directory: %s\n", dirname); 8 | 9 | File root = fs.open(dirname); 10 | if(!root){ 11 | Serial.println("Failed to open directory"); 12 | return; 13 | } 14 | if(!root.isDirectory()){ 15 | Serial.println("Not a directory"); 16 | return; 17 | } 18 | 19 | File file = root.openNextFile(); 20 | while(file){ 21 | if(file.isDirectory()){ 22 | Serial.print(" DIR : "); 23 | Serial.println(file.name()); 24 | if(levels){ 25 | listDir(fs, file.name(), levels -1); 26 | } 27 | } else { 28 | Serial.print(" FILE: "); 29 | Serial.print(file.name()); 30 | Serial.print(" SIZE: "); 31 | Serial.println(file.size()); 32 | } 33 | file = root.openNextFile(); 34 | } 35 | } 36 | 37 | void createDir(fs::FS &fs, const char * path){ 38 | Serial.printf("Creating Dir: %s\n", path); 39 | if(fs.mkdir(path)){ 40 | Serial.println("Dir created"); 41 | } else { 42 | Serial.println("mkdir failed"); 43 | } 44 | } 45 | 46 | void removeDir(fs::FS &fs, const char * path){ 47 | Serial.printf("Removing Dir: %s\n", path); 48 | if(fs.rmdir(path)){ 49 | Serial.println("Dir removed"); 50 | } else { 51 | Serial.println("rmdir failed"); 52 | } 53 | } 54 | 55 | void readFile(fs::FS &fs, const char * path){ 56 | Serial.printf("Reading file: %s\n", path); 57 | 58 | File file = fs.open(path); 59 | if(!file){ 60 | Serial.println("Failed to open file for reading"); 61 | return; 62 | } 63 | 64 | Serial.print("Read from file: "); 65 | while(file.available()){ 66 | Serial.write(file.read()); 67 | } 68 | file.close(); 69 | } 70 | 71 | void writeFile(fs::FS &fs, const char * path, const char * message){ 72 | Serial.printf("Writing file: %s\n", path); 73 | 74 | File file = fs.open(path, FILE_WRITE); 75 | if(!file){ 76 | Serial.println("Failed to open file for writing"); 77 | return; 78 | } 79 | if(file.print(message)){ 80 | Serial.println("File written"); 81 | } else { 82 | Serial.println("Write failed"); 83 | } 84 | file.close(); 85 | } 86 | 87 | void appendFile(fs::FS &fs, const char * path, const char * message){ 88 | Serial.printf("Appending to file: %s\n", path); 89 | 90 | File file = fs.open(path, FILE_APPEND); 91 | if(!file){ 92 | Serial.println("Failed to open file for appending"); 93 | return; 94 | } 95 | if(file.print(message)){ 96 | Serial.println("Message appended"); 97 | } else { 98 | Serial.println("Append failed"); 99 | } 100 | file.close(); 101 | } 102 | 103 | void renameFile(fs::FS &fs, const char * path1, const char * path2){ 104 | Serial.printf("Renaming file %s to %s\n", path1, path2); 105 | if (fs.rename(path1, path2)) { 106 | Serial.println("File renamed"); 107 | } else { 108 | Serial.println("Rename failed"); 109 | } 110 | } 111 | 112 | void deleteFile(fs::FS &fs, const char * path){ 113 | Serial.printf("Deleting file: %s\n", path); 114 | if(fs.remove(path)){ 115 | Serial.println("File deleted"); 116 | } else { 117 | Serial.println("Delete failed"); 118 | } 119 | } 120 | 121 | void testFileIO(fs::FS &fs, const char * path){ 122 | File file = fs.open(path); 123 | static uint8_t buf[512]; 124 | size_t len = 0; 125 | uint32_t start = millis(); 126 | uint32_t end = start; 127 | if(file){ 128 | len = file.size(); 129 | size_t flen = len; 130 | start = millis(); 131 | while(len){ 132 | size_t toRead = len; 133 | if(toRead > 512){ 134 | toRead = 512; 135 | } 136 | file.read(buf, toRead); 137 | len -= toRead; 138 | } 139 | end = millis() - start; 140 | Serial.printf("%u bytes read for %u ms\n", flen, end); 141 | file.close(); 142 | } else { 143 | Serial.println("Failed to open file for reading"); 144 | } 145 | 146 | 147 | file = fs.open(path, FILE_WRITE); 148 | if(!file){ 149 | Serial.println("Failed to open file for writing"); 150 | return; 151 | } 152 | 153 | size_t i; 154 | start = millis(); 155 | for(i=0; i<2048; i++){ 156 | file.write(buf, 512); 157 | } 158 | end = millis() - start; 159 | Serial.printf("%u bytes written for %u ms\n", 2048 * 512, end); 160 | file.close(); 161 | } 162 | 163 | void setup(){ 164 | Serial.begin(115200); 165 | SPI.begin(18,19,23,5); 166 | if(!SD.begin(22,SPI)){ 167 | Serial.println("Card Mount Failed"); 168 | return; 169 | } 170 | uint8_t cardType = SD.cardType(); 171 | 172 | if(cardType == CARD_NONE){ 173 | Serial.println("No SD card attached"); 174 | return; 175 | } 176 | 177 | Serial.print("SD Card Type: "); 178 | if(cardType == CARD_MMC){ 179 | Serial.println("MMC"); 180 | } else if(cardType == CARD_SD){ 181 | Serial.println("SDSC"); 182 | } else if(cardType == CARD_SDHC){ 183 | Serial.println("SDHC"); 184 | } else { 185 | Serial.println("UNKNOWN"); 186 | } 187 | 188 | uint64_t cardSize = SD.cardSize() / (1024 * 1024); 189 | Serial.printf("SD Card Size: %lluMB\n", cardSize); 190 | 191 | listDir(SD, "/", 0); 192 | createDir(SD, "/mydir"); 193 | listDir(SD, "/", 0); 194 | removeDir(SD, "/mydir"); 195 | listDir(SD, "/", 2); 196 | writeFile(SD, "/hello.txt", "Hello "); 197 | appendFile(SD, "/hello.txt", "World!\n"); 198 | readFile(SD, "/hello.txt"); 199 | deleteFile(SD, "/foo.txt"); 200 | renameFile(SD, "/hello.txt", "/foo.txt"); 201 | readFile(SD, "/foo.txt"); 202 | testFileIO(SD, "/test.txt"); 203 | Serial.printf("Total space: %lluMB\n", SD.totalBytes() / (1024 * 1024)); 204 | Serial.printf("Used space: %lluMB\n", SD.usedBytes() / (1024 * 1024)); 205 | } 206 | 207 | void loop(){ 208 | 209 | } -------------------------------------------------------------------------------- /old-src/esp32_ssd1306test/esp32_ssd1306test.ino: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | This is an example for our Monochrome OLEDs based on SSD1306 drivers 3 | 4 | Pick one up today in the adafruit shop! 5 | ------> http://www.adafruit.com/category/63_98 6 | 7 | This example is for a 128x32 pixel display using I2C to communicate 8 | 3 pins are required to interface (two I2C and one reset). 9 | 10 | Adafruit invests time and resources providing this open 11 | source code, please support Adafruit and open-source 12 | hardware by purchasing products from Adafruit! 13 | 14 | Written by Limor Fried/Ladyada for Adafruit Industries, 15 | with contributions from the open source community. 16 | BSD license, check license.txt for more information 17 | All text above, and the splash screen below must be 18 | included in any redistribution. 19 | **************************************************************************/ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #define MAKEPYTHON_ESP32_SDA 4 27 | #define MAKEPYTHON_ESP32_SCL 5 28 | 29 | #define SCREEN_WIDTH 128 // OLED display width, in pixels 30 | #define SCREEN_HEIGHT 64 // OLED display height, in pixels 31 | 32 | // Declaration for an SSD1306 display connected to I2C (SDA, SCL pins) 33 | #define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin) 34 | 35 | //Wire.begin(4,5); 36 | Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); 37 | 38 | #define NUMFLAKES 10 // Number of snowflakes in the animation example 39 | 40 | #define LOGO_HEIGHT 16 41 | #define LOGO_WIDTH 16 42 | static const unsigned char PROGMEM logo_bmp[] = 43 | { B00000000, B11000000, 44 | B00000001, B11000000, 45 | B00000001, B11000000, 46 | B00000011, B11100000, 47 | B11110011, B11100000, 48 | B11111110, B11111000, 49 | B01111110, B11111111, 50 | B00110011, B10011111, 51 | B00011111, B11111100, 52 | B00001101, B01110000, 53 | B00011011, B10100000, 54 | B00111111, B11100000, 55 | B00111111, B11110000, 56 | B01111100, B11110000, 57 | B01110000, B01110000, 58 | B00000000, B00110000 }; 59 | 60 | void setup() { 61 | Serial.begin(115200); 62 | Wire.begin(MAKEPYTHON_ESP32_SDA,MAKEPYTHON_ESP32_SCL); 63 | // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally 64 | if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x32 65 | Serial.println(F("SSD1306 allocation failed")); 66 | for(;;); // Don't proceed, loop forever 67 | } 68 | 69 | // Show initial display buffer contents on the screen -- 70 | // the library initializes this with an Adafruit splash screen. 71 | display.display(); 72 | delay(2000); // Pause for 2 seconds 73 | 74 | // Clear the buffer 75 | display.clearDisplay(); 76 | 77 | // Draw a single pixel in white 78 | display.drawPixel(10, 10, SSD1306_WHITE); 79 | 80 | // Show the display buffer on the screen. You MUST call display() after 81 | // drawing commands to make them visible on screen! 82 | display.display(); 83 | delay(2000); 84 | // display.display() is NOT necessary after every single drawing command, 85 | // unless that's what you want...rather, you can batch up a bunch of 86 | // drawing operations and then update the screen all at once by calling 87 | // display.display(). These examples demonstrate both approaches... 88 | 89 | testdrawline(); // Draw many lines 90 | 91 | testdrawrect(); // Draw rectangles (outlines) 92 | 93 | testfillrect(); // Draw rectangles (filled) 94 | 95 | testdrawcircle(); // Draw circles (outlines) 96 | 97 | testfillcircle(); // Draw circles (filled) 98 | 99 | testdrawroundrect(); // Draw rounded rectangles (outlines) 100 | 101 | testfillroundrect(); // Draw rounded rectangles (filled) 102 | 103 | testdrawtriangle(); // Draw triangles (outlines) 104 | 105 | testfilltriangle(); // Draw triangles (filled) 106 | 107 | testdrawchar(); // Draw characters of the default font 108 | 109 | testdrawstyles(); // Draw 'stylized' characters 110 | 111 | testscrolltext(); // Draw scrolling text 112 | 113 | testdrawbitmap(); // Draw a small bitmap image 114 | 115 | // Invert and restore display, pausing in-between 116 | display.invertDisplay(true); 117 | delay(1000); 118 | display.invertDisplay(false); 119 | delay(1000); 120 | 121 | testanimate(logo_bmp, LOGO_WIDTH, LOGO_HEIGHT); // Animate bitmaps 122 | } 123 | 124 | void loop() { 125 | } 126 | 127 | void testdrawline() { 128 | int16_t i; 129 | 130 | display.clearDisplay(); // Clear display buffer 131 | 132 | for(i=0; i=0; i-=4) { 152 | display.drawLine(0, display.height()-1, display.width()-1, i, SSD1306_WHITE); 153 | display.display(); 154 | delay(1); 155 | } 156 | delay(250); 157 | 158 | display.clearDisplay(); 159 | 160 | for(i=display.width()-1; i>=0; i-=4) { 161 | display.drawLine(display.width()-1, display.height()-1, i, 0, SSD1306_WHITE); 162 | display.display(); 163 | delay(1); 164 | } 165 | for(i=display.height()-1; i>=0; i-=4) { 166 | display.drawLine(display.width()-1, display.height()-1, 0, i, SSD1306_WHITE); 167 | display.display(); 168 | delay(1); 169 | } 170 | delay(250); 171 | 172 | display.clearDisplay(); 173 | 174 | for(i=0; i0; i-=3) { 229 | // The INVERSE color is used so circles alternate white/black 230 | display.fillCircle(display.width() / 2, display.height() / 2, i, SSD1306_INVERSE); 231 | display.display(); // Update screen with each newly-drawn circle 232 | delay(1); 233 | } 234 | 235 | delay(2000); 236 | } 237 | 238 | void testdrawroundrect(void) { 239 | display.clearDisplay(); 240 | 241 | for(int16_t i=0; i0; i-=5) { 284 | // The INVERSE color is used so triangles alternate white/black 285 | display.fillTriangle( 286 | display.width()/2 , display.height()/2-i, 287 | display.width()/2-i, display.height()/2+i, 288 | display.width()/2+i, display.height()/2+i, SSD1306_INVERSE); 289 | display.display(); 290 | delay(1); 291 | } 292 | 293 | delay(2000); 294 | } 295 | 296 | void testdrawchar(void) { 297 | display.clearDisplay(); 298 | 299 | display.setTextSize(1); // Normal 1:1 pixel scale 300 | display.setTextColor(SSD1306_WHITE); // Draw white text 301 | display.setCursor(0, 0); // Start at top-left corner 302 | display.cp437(true); // Use full 256 char 'Code Page 437' font 303 | 304 | // Not all the characters will fit on the display. This is normal. 305 | // Library will draw what it can and the rest will be clipped. 306 | for(int16_t i=0; i<256; i++) { 307 | if(i == '\n') display.write(' '); 308 | else display.write(i); 309 | } 310 | 311 | display.display(); 312 | delay(2000); 313 | } 314 | 315 | void testdrawstyles(void) { 316 | display.clearDisplay(); 317 | 318 | display.setTextSize(1); // Normal 1:1 pixel scale 319 | display.setTextColor(SSD1306_WHITE); // Draw white text 320 | display.setCursor(0,0); // Start at top-left corner 321 | display.println(F("Hello, world!")); 322 | 323 | display.setTextColor(SSD1306_BLACK, SSD1306_WHITE); // Draw 'inverse' text 324 | display.println(3.141592); 325 | 326 | display.setTextSize(2); // Draw 2X-scale text 327 | display.setTextColor(SSD1306_WHITE); 328 | display.print(F("0x")); display.println(0xDEADBEEF, HEX); 329 | 330 | display.display(); 331 | delay(2000); 332 | } 333 | 334 | void testscrolltext(void) { 335 | display.clearDisplay(); 336 | 337 | display.setTextSize(2); // Draw 2X-scale text 338 | display.setTextColor(SSD1306_WHITE); 339 | display.setCursor(10, 0); 340 | display.println(F("scroll")); 341 | display.display(); // Show initial text 342 | delay(100); 343 | 344 | // Scroll in various directions, pausing in-between: 345 | display.startscrollright(0x00, 0x0F); 346 | delay(2000); 347 | display.stopscroll(); 348 | delay(1000); 349 | display.startscrollleft(0x00, 0x0F); 350 | delay(2000); 351 | display.stopscroll(); 352 | delay(1000); 353 | display.startscrolldiagright(0x00, 0x07); 354 | delay(2000); 355 | display.startscrolldiagleft(0x00, 0x07); 356 | delay(2000); 357 | display.stopscroll(); 358 | delay(1000); 359 | } 360 | 361 | void testdrawbitmap(void) { 362 | display.clearDisplay(); 363 | 364 | display.drawBitmap( 365 | (display.width() - LOGO_WIDTH ) / 2, 366 | (display.height() - LOGO_HEIGHT) / 2, 367 | logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1); 368 | display.display(); 369 | delay(1000); 370 | } 371 | 372 | #define XPOS 0 // Indexes into the 'icons' array in function below 373 | #define YPOS 1 374 | #define DELTAY 2 375 | 376 | void testanimate(const uint8_t *bitmap, uint8_t w, uint8_t h) { 377 | int8_t f, icons[NUMFLAKES][3]; 378 | 379 | // Initialize 'snowflake' positions 380 | for(f=0; f< NUMFLAKES; f++) { 381 | icons[f][XPOS] = random(1 - LOGO_WIDTH, display.width()); 382 | icons[f][YPOS] = -LOGO_HEIGHT; 383 | icons[f][DELTAY] = random(1, 6); 384 | Serial.print(F("x: ")); 385 | Serial.print(icons[f][XPOS], DEC); 386 | Serial.print(F(" y: ")); 387 | Serial.print(icons[f][YPOS], DEC); 388 | Serial.print(F(" dy: ")); 389 | Serial.println(icons[f][DELTAY], DEC); 390 | } 391 | 392 | for(;;) { // Loop forever... 393 | display.clearDisplay(); // Clear the display buffer 394 | 395 | // Draw each snowflake: 396 | for(f=0; f< NUMFLAKES; f++) { 397 | display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, SSD1306_WHITE); 398 | } 399 | 400 | display.display(); // Show the display buffer on the screen 401 | delay(200); // Pause for 1/10 second 402 | 403 | // Then update coordinates of each flake... 404 | for(f=0; f< NUMFLAKES; f++) { 405 | icons[f][YPOS] += icons[f][DELTAY]; 406 | // If snowflake is off the bottom of the screen... 407 | if (icons[f][YPOS] >= display.height()) { 408 | // Reinitialize to a random position, just off the top 409 | icons[f][XPOS] = random(1 - LOGO_WIDTH, display.width()); 410 | icons[f][YPOS] = -LOGO_HEIGHT; 411 | icons[f][DELTAY] = random(1, 6); 412 | } 413 | } 414 | } 415 | } 416 | -------------------------------------------------------------------------------- /old-src/esp32_wav_player/I2S.cpp: -------------------------------------------------------------------------------- 1 | #include "I2S.h" 2 | 3 | void I2S_Init() { 4 | i2s_config_t i2s_config = { 5 | .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX), 6 | .sample_rate = SAMPLE_RATE, 7 | .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, 8 | .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //2-channels 9 | .communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB), 10 | .intr_alloc_flags = 0, 11 | .dma_buf_count = 16, 12 | .dma_buf_len = 60 13 | }; 14 | 15 | i2s_pin_config_t pin_config = { 16 | .bck_io_num = PIN_I2S_BCLK, 17 | .ws_io_num = PIN_I2S_LRC, 18 | .data_out_num = PIN_I2S_DOUT, 19 | .data_in_num = -1 //Not used 20 | }; 21 | i2s_driver_install((i2s_port_t)0, &i2s_config, 0, NULL); 22 | i2s_set_pin((i2s_port_t)0, &pin_config); 23 | i2s_set_clk((i2s_port_t)0, SAMPLE_RATE, (i2s_bits_per_sample_t)16, (i2s_channel_t)2); 24 | } 25 | 26 | void I2S_Write(char* data, int numData) { 27 | i2s_write_bytes((i2s_port_t)0, (const char *)data, numData, portMAX_DELAY); 28 | } 29 | 30 | -------------------------------------------------------------------------------- /old-src/esp32_wav_player/I2S.h: -------------------------------------------------------------------------------- 1 | #include "freertos/FreeRTOS.h" 2 | #include "freertos/task.h" 3 | #include "driver/i2s.h" 4 | #include "esp_system.h" 5 | #define SAMPLE_RATE (44100) 6 | #define PIN_I2S_BCLK 26 7 | #define PIN_I2S_LRC 25 8 | #define PIN_I2S_DOUT 27 9 | 10 | // 44100Hz, 16bit, stereo 11 | void I2S_Init(); 12 | void I2S_Write(char* data, int numData); -------------------------------------------------------------------------------- /old-src/esp32_wav_player/esp32_wav_player.ino: -------------------------------------------------------------------------------- 1 | #include "I2S.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define MAKEPYTHON_ESP32_SDA 4 9 | #define MAKEPYTHON_ESP32_SCL 5 10 | 11 | #define SCREEN_WIDTH 128 // OLED display width, in pixels 12 | #define SCREEN_HEIGHT 64 // OLED display height, in pixels 13 | 14 | // Declaration for an SSD1306 display connected to I2C (SDA, SCL pins) 15 | #define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin) 16 | 17 | Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); 18 | 19 | const int Pin_up = 39; 20 | const int Pin_down = 36; 21 | const int Pin_pause = 35; 22 | const int Pin_mute = 34; 23 | 24 | const int offset = 0x2C; 25 | char data[800]; 26 | char null_data[4] = {0, 0, 0, 0}; 27 | long i = 0; 28 | String music_list[30]; 29 | int music_num = 0; 30 | int music_index = 0; 31 | 32 | void setup() 33 | { 34 | pinMode(Pin_down, INPUT_PULLUP); 35 | pinMode(Pin_up, INPUT_PULLUP); 36 | pinMode(Pin_pause, INPUT_PULLUP); 37 | pinMode(Pin_mute, OUTPUT); 38 | digitalWrite(Pin_mute, LOW); 39 | 40 | Serial.begin(115200); 41 | Wire.begin(MAKEPYTHON_ESP32_SDA, MAKEPYTHON_ESP32_SCL); 42 | // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally 43 | if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) 44 | { // Address 0x3C for 128x32 45 | Serial.println(F("SSD1306 allocation failed")); 46 | for (;;) 47 | ; // Don't proceed, loop forever 48 | } 49 | display.clearDisplay(); 50 | logoshow(); 51 | 52 | SPI.begin(18, 19, 23, 5); 53 | if (!SD.begin(22, SPI)) 54 | { 55 | Serial.println("Card Mount Failed"); 56 | return; 57 | } 58 | //listDir(SD, "/", 0); 59 | music_num = get_wav_list(SD, "/", 0, music_list); 60 | Serial.print("Wav count:"); 61 | Serial.println(music_num); 62 | 63 | music_num--; 64 | Serial.println("All wav:"); 65 | for (int i = 0; i < music_num; i++) 66 | { 67 | Serial.println(music_list[i]); 68 | } 69 | } 70 | 71 | void loop() 72 | { 73 | Serial.print("Wav index:"); 74 | Serial.println(music_index); 75 | String wav_name = music_list[music_index]; 76 | File file = SD.open(wav_name); // 44100Hz, 16bit, linear PCM 77 | 78 | file.seek(22); 79 | int ch = 2; 80 | long int music_time = file.size() / 160000; 81 | 82 | Serial.print(wav_name + " "); 83 | Serial.println("OPEN FILE"); 84 | 85 | display.clearDisplay(); 86 | 87 | display.setTextSize(1); // Normal 1:1 pixel scale 88 | display.setTextColor(SSD1306_WHITE); // Draw white text 89 | display.setCursor(0, 0); // Start at top-left corner 90 | display.println(wav_name); 91 | display.setCursor(0, 12); 92 | display.println("44100Hz"); 93 | display.setCursor(0, 24); 94 | display.print(ch); 95 | display.println(" Channel"); 96 | display.setCursor(0, 36); 97 | display.print(music_time); 98 | display.println(" seconds"); 99 | display.display(); 100 | delay(2000); 101 | 102 | file.seek(offset); 103 | 104 | I2S_Init(); 105 | Serial.println("I2S"); 106 | 107 | while (file.readBytes(data, sizeof(data))) 108 | { 109 | 110 | if (digitalRead(Pin_down) == 0) 111 | { 112 | Serial.println("Pin_down"); 113 | if (music_index < music_num) 114 | music_index++; 115 | else 116 | music_index = 0; 117 | delay(100); 118 | break; 119 | } 120 | if (digitalRead(Pin_up) == 0) 121 | { 122 | Serial.println("Pin_up"); 123 | if (music_index == 0) 124 | music_index = music_num; 125 | else 126 | music_index--; 127 | delay(100); 128 | break; 129 | } 130 | if (digitalRead(Pin_pause) == 0) 131 | { 132 | Serial.println("Pin_pause"); 133 | digitalWrite(Pin_mute, HIGH); 134 | for (int i = 0; i < sizeof(data); ++i) 135 | data[i] = 0; // to prevent buzzing 136 | for (int i = 0; i < 5; ++i) 137 | I2S_Write(data, sizeof(data)); 138 | delay(1000); 139 | while (1) 140 | { 141 | if (digitalRead(Pin_pause) == 0) 142 | { 143 | Serial.println("Pin_pause_play"); 144 | delay(1000); 145 | digitalWrite(Pin_mute, LOW); 146 | break; 147 | } 148 | } 149 | } 150 | I2S_Write(data, sizeof(data)); 151 | } 152 | file.close(); 153 | for (int i = 0; i < sizeof(data); ++i) 154 | data[i] = 0; // to prevent buzzing 155 | for (int i = 0; i < 5; ++i) 156 | I2S_Write(data, sizeof(data)); 157 | 158 | Serial.println("over"); 159 | } 160 | 161 | int get_wav_list(fs::FS &fs, const char *dirname, uint8_t levels, String wavlist[30]) 162 | { 163 | Serial.printf("Listing directory: %s\n", dirname); 164 | int i = 0; 165 | 166 | File root = fs.open(dirname); 167 | if (!root) 168 | { 169 | Serial.println("Failed to open directory"); 170 | return i; 171 | } 172 | if (!root.isDirectory()) 173 | { 174 | Serial.println("Not a directory"); 175 | return i; 176 | } 177 | 178 | File file = root.openNextFile(); 179 | while (file) 180 | { 181 | if (file.isDirectory()) 182 | { 183 | } 184 | else 185 | { 186 | String temp = file.name(); 187 | if (temp.endsWith(".wav")) 188 | { 189 | wavlist[i] = temp; 190 | i++; 191 | } 192 | } 193 | file = root.openNextFile(); 194 | } 195 | return i; 196 | } 197 | 198 | void mydisplay(int wav_index) 199 | { 200 | display.clearDisplay(); 201 | 202 | display.setTextSize(1); // Normal 1:1 pixel scale 203 | display.setTextColor(SSD1306_WHITE); // Draw white text 204 | display.setCursor(0, 0); // Start at top-left corner 205 | display.println(music_list[wav_index]); 206 | display.setCursor(0, 12); 207 | display.println("44100Hz"); 208 | display.setCursor(0, 24); 209 | display.println("2 Channel"); 210 | display.display(); 211 | delay(2000); 212 | } 213 | 214 | void logoshow(void) 215 | { 216 | display.clearDisplay(); 217 | 218 | display.setTextSize(2); // Normal 1:1 pixel scale 219 | display.setTextColor(SSD1306_WHITE); // Draw white text 220 | display.setCursor(0, 0); // Start at top-left corner 221 | display.println(F("MakePython")); 222 | display.setCursor(0, 20); // Start at top-left corner 223 | display.println(F("Audio")); 224 | display.setCursor(0, 40); // Start at top-left corner 225 | display.println(F("WAVPLAYER")); 226 | display.display(); 227 | delay(2000); 228 | } -------------------------------------------------------------------------------- /old-src/micropython_code/esp32_tts.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Makerfabs/Project_MakePython_Audio_Music/3675eecd3b1562700e8ce36420fdf39be5d961e1/old-src/micropython_code/esp32_tts.bin -------------------------------------------------------------------------------- /old-src/micropython_code/workSpace/__pycache__/sdcard.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Makerfabs/Project_MakePython_Audio_Music/3675eecd3b1562700e8ce36420fdf39be5d961e1/old-src/micropython_code/workSpace/__pycache__/sdcard.cpython-38.pyc -------------------------------------------------------------------------------- /old-src/micropython_code/workSpace/audio_set.py: -------------------------------------------------------------------------------- 1 | 2 | from machine import I2S 3 | from machine import Pin 4 | import array 5 | import gc 6 | import speech 7 | 8 | 9 | class audio: 10 | def __init__(self): 11 | super().__init__() 12 | bck_pin = Pin(26) 13 | ws_pin = Pin(25) 14 | sdout_pin = Pin(27) 15 | self.audio_out = I2S(I2S.NUM0, 16 | bck=bck_pin, 17 | ws=ws_pin, 18 | sdout=sdout_pin, 19 | standard=I2S.PHILIPS, 20 | mode=I2S.MASTER_TX, 21 | dataformat=I2S.B16, 22 | channelformat=I2S.ONLY_RIGHT, 23 | samplerate=16000, 24 | #samplerate=44100, 25 | dmacount=16, 26 | dmalen=512) 27 | 28 | 29 | def say(self,text): 30 | a = bytearray(4000*8) 31 | size = speech.say(text, a , pitch=80, speed=72, mouth=128, throat=128) 32 | self.audio_out.write(a[:size]) 33 | del a 34 | gc.collect() 35 | 36 | 37 | def close(self): 38 | self.audio_out.deinit() 39 | 40 | def say_sentance(self,text): 41 | list = text.split() 42 | print(list) 43 | for word in list: 44 | print(word) 45 | self.say(word) 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /old-src/micropython_code/workSpace/display_ssd1306_i2c.py: -------------------------------------------------------------------------------- 1 | 2 | # https://learn.adafruit.com/micropython-hardware-ssd1306-oled-display/software 3 | import time 4 | import machine 5 | import ssd1306 6 | 7 | 8 | class Display: 9 | 10 | def __init__(self, 11 | width = 128, height = 64, 12 | scl_pin_id = 5, sda_pin_id = 4, 13 | freq = 400000): 14 | 15 | self.width = width 16 | self.height = height 17 | self.i2c = machine.I2C(scl = machine.Pin(scl_pin_id, machine.Pin.OUT), 18 | sda = machine.Pin(sda_pin_id), 19 | freq = freq) 20 | self.display = ssd1306.SSD1306_I2C(width, height, self.i2c) 21 | self.show = self.display.show 22 | 23 | def fill_rect(self, x, y, w, h, c): 24 | self.display.fill_rect(x, y, w, h, c) 25 | self.display.show() 26 | 27 | 28 | def clear(self): 29 | self.display.fill(0) 30 | self.display.show() 31 | 32 | 33 | def show_text(self, text, x = 0, y = 0, clear_first = True, show_now = True, hold_seconds = 0): 34 | if clear_first: self.display.fill(0) 35 | self.display.text(text, x, y) 36 | if show_now: 37 | self.display.show() 38 | if hold_seconds > 0: time.sleep(hold_seconds) 39 | 40 | 41 | def wrap(self, text, start_line = 0, 42 | height_per_line = 8, width_per_char = 8, 43 | start_pixel_each_line = 0): 44 | 45 | chars_per_line = self.width//width_per_char 46 | max_lines = self.height//height_per_line - start_line 47 | lines = [(text[chars_per_line*line: chars_per_line*(line+1)], start_pixel_each_line, height_per_line*(line+start_line)) 48 | for line in range(max_lines)] 49 | 50 | return lines 51 | 52 | 53 | def show_text_wrap(self, text, 54 | start_line = 0, height_per_line = 8, width_per_char = 8, start_pixel_each_line = 0, 55 | clear_first = True, show_now = True, hold_seconds = 0): 56 | 57 | if clear_first: self.clear() 58 | 59 | for line, x, y in self.wrap(text, start_line, height_per_line, width_per_char, start_pixel_each_line): 60 | self.show_text(line, x, y, clear_first = False, show_now = False) 61 | 62 | if show_now: 63 | self.display.show() 64 | if hold_seconds > 0: time.sleep(hold_seconds) 65 | 66 | 67 | def show_datetime(self, year, month, day, hour, minute, second): 68 | datetime = [year, month, day, hour, minute, second] 69 | datetime_str = ["{0:0>2}".format(d) for d in datetime] 70 | 71 | self.show_text(text = '-'.join(datetime_str[:3]), 72 | x = 0, y = 0, clear_first = True, show_now = False) 73 | self.show_text(text = ':'.join(datetime_str[3:6]), 74 | x = 0, y = 10, clear_first = False, show_now = True) 75 | 76 | 77 | def show_time(self, year, month, day, hour, minute, second): 78 | self.show_datetime(year, month, day, hour, minute, second) 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /old-src/micropython_code/workSpace/music.py: -------------------------------------------------------------------------------- 1 | import sdread 2 | import display_ssd1306_i2c 3 | from machine import Pin, SPI, I2S 4 | import time 5 | 6 | class Music(): 7 | def __init__(self): 8 | #obj 9 | self.Lcd = display_ssd1306_i2c.Display() 10 | self.Audio = None 11 | self.SDcard = None 12 | self.SPI = None 13 | 14 | #GPIO 15 | self.Pin_up = Pin(39,Pin.IN,Pin.PULL_UP) 16 | self.Pin_down = Pin(36,Pin.IN,Pin.PULL_UP) 17 | self.Pin_play = Pin(35,Pin.IN,Pin.PULL_UP) 18 | self.bck_pin = Pin(26) 19 | self.ws_pin = Pin(25) 20 | self.sdout_pin = Pin(27) 21 | 22 | #var 23 | self.index = 0 24 | self.last_index = -1 25 | self.play_status = 0 26 | self.wav_list = None 27 | self.wav_name = None 28 | 29 | pass 30 | 31 | def Audio_init(self): 32 | I2S_dataformat = I2S.B16 33 | I2S_channel = I2S.ONLY_LEFT 34 | I2S_samplerate = 44100 35 | self.Audio = I2S(I2S.NUM0, 36 | bck=self.bck_pin, ws=self.ws_pin, sdout=self.sdout_pin, 37 | standard=I2S.PHILIPS, 38 | mode=I2S.MASTER_TX, 39 | dataformat=I2S_dataformat, 40 | channelformat=I2S_channel, 41 | samplerate=I2S_samplerate, 42 | dmacount=10, dmalen=512) 43 | 44 | def Audio_close(self): 45 | self.Audio.deinit() 46 | 47 | def Audio_play(self): 48 | wav_file = '/sd/{}'.format(self.wav_name) 49 | wav = open(wav_file,'rb') 50 | 51 | # advance to first byte of Data section in WAV file 52 | pos = wav.seek(44) 53 | 54 | # allocate sample arrays 55 | # memoryview used to reduce heap allocation in while loop 56 | wav_samples = bytearray(2048) 57 | wav_samples_mv = memoryview(wav_samples) 58 | 59 | print('Starting') 60 | # continuously read audio samples from the WAV file 61 | # and write them to an I2S DAC 62 | while True: 63 | try: 64 | num_read = wav.readinto(wav_samples_mv) 65 | 66 | """ 67 | for i in range(len(wav_samples_mv)): 68 | wav_samples_mv[i] = int(wav_samples_mv[i]/2) 69 | #wav_samples_mv[i] =wav_samples_mv[i] + int ((128 - wav_samples_mv[i]) / 2) 70 | pass 71 | """ 72 | 73 | num_written = 0 74 | # end of WAV file? 75 | if num_read == 0: 76 | # advance to first byte of Data section 77 | pos = wav.seek(44) 78 | else: 79 | # loop until all samples are written to the I2S peripheral 80 | while num_written < num_read: 81 | num_written += self.Audio.write(wav_samples_mv[num_written:num_read], timeout=0) 82 | if self.Pin_play.value() == 0: 83 | wav.close() 84 | self.Audio.deinit() 85 | self.play_status = 0 86 | time.sleep(0.5) 87 | print('Hand Out') 88 | return 89 | except (KeyboardInterrupt, Exception) as e: 90 | print('caught exception {} {}'.format(type(e).__name__, e)) 91 | break 92 | 93 | wav.close() 94 | self.Audio.deinit() 95 | print('Auto Out') 96 | 97 | def SDcard_init(self): 98 | self.SDcard = sdread.init_SD() 99 | sdread.mount(self.SDcard) 100 | self.wav_list = sdread.get_wav_list(self.SDcard) 101 | 102 | def SDcard_close(self): 103 | pass 104 | 105 | def Display_list(self): 106 | self.Lcd.clear() 107 | 108 | if self.index - 2 >= 0: 109 | self.Lcd.show_text(self.wav_list[self.index - 2],0,0,False,False) 110 | 111 | if self.index - 1 >= 0: 112 | self.Lcd.show_text(self.wav_list[self.index - 1],0,12,False,False) 113 | 114 | self.Lcd.show_text(self.wav_list[self.index],0,24,False,False) 115 | 116 | if self.index + 1 < len(self.wav_list): 117 | self.Lcd.show_text(self.wav_list[self.index + 1],0,36,False,False) 118 | 119 | if self.index + 2 < len(self.wav_list): 120 | self.Lcd.show_text(self.wav_list[self.index + 2],0,48,False,False) 121 | 122 | self.Lcd.display.line(0,22,127,22,1) 123 | self.Lcd.display.line(0,34,127,34,1) 124 | self.Lcd.show() 125 | 126 | def Keyboard_scanf(self): 127 | if self.Pin_up.value() == 0 : 128 | print("up") 129 | if self.index > 0: 130 | self.index -= 1 131 | if self.Pin_down.value() == 0 : 132 | print("down") 133 | if self.index < len(self.wav_list) - 1: 134 | self.index += 1 135 | if self.Pin_play.value() == 0 : 136 | print("play") 137 | self.play_status = 1 138 | self.wav_name = self.wav_list[self.index] 139 | time.sleep(0.5) 140 | -------------------------------------------------------------------------------- /old-src/micropython_code/workSpace/sdcard.py: -------------------------------------------------------------------------------- 1 | """ 2 | MicroPython driver for SD cards using SPI bus. 3 | 4 | Requires an SPI bus and a CS pin. Provides readblocks and writeblocks 5 | methods so the device can be mounted as a filesystem. 6 | 7 | Example usage on pyboard: 8 | 9 | import pyb, sdcard, os 10 | sd = sdcard.SDCard(pyb.SPI(1), pyb.Pin.board.X5) 11 | pyb.mount(sd, '/sd2') 12 | os.listdir('/') 13 | 14 | Example usage on ESP8266: 15 | 16 | import machine, sdcard, os 17 | sd = sdcard.SDCard(machine.SPI(1), machine.Pin(15)) 18 | os.mount(sd, '/sd') 19 | os.listdir('/') 20 | 21 | """ 22 | 23 | from micropython import const 24 | import time 25 | 26 | 27 | _CMD_TIMEOUT = const(100) 28 | 29 | _R1_IDLE_STATE = const(1 << 0) 30 | # R1_ERASE_RESET = const(1 << 1) 31 | _R1_ILLEGAL_COMMAND = const(1 << 2) 32 | # R1_COM_CRC_ERROR = const(1 << 3) 33 | # R1_ERASE_SEQUENCE_ERROR = const(1 << 4) 34 | # R1_ADDRESS_ERROR = const(1 << 5) 35 | # R1_PARAMETER_ERROR = const(1 << 6) 36 | _TOKEN_CMD25 = const(0xFC) 37 | _TOKEN_STOP_TRAN = const(0xFD) 38 | _TOKEN_DATA = const(0xFE) 39 | 40 | 41 | class SDCard: 42 | def __init__(self, spi, cs): 43 | self.spi = spi 44 | self.cs = cs 45 | 46 | self.cmdbuf = bytearray(6) 47 | self.dummybuf = bytearray(512) 48 | self.tokenbuf = bytearray(1) 49 | for i in range(512): 50 | self.dummybuf[i] = 0xFF 51 | self.dummybuf_memoryview = memoryview(self.dummybuf) 52 | 53 | # initialise the card 54 | self.init_card() 55 | 56 | def init_spi(self, baudrate): 57 | try: 58 | master = self.spi.MASTER 59 | except AttributeError: 60 | # on ESP8266 61 | self.spi.init(baudrate=baudrate, phase=0, polarity=0) 62 | else: 63 | # on pyboard 64 | self.spi.init(master, baudrate=baudrate, phase=0, polarity=0) 65 | 66 | def init_card(self): 67 | # init CS pin 68 | self.cs.init(self.cs.OUT, value=1) 69 | 70 | # init SPI bus; use low data rate for initialisation 71 | self.init_spi(100000) 72 | 73 | # clock card at least 100 cycles with cs high 74 | for i in range(16): 75 | self.spi.write(b"\xff") 76 | 77 | # CMD0: init card; should return _R1_IDLE_STATE (allow 5 attempts) 78 | for _ in range(5): 79 | if self.cmd(0, 0, 0x95) == _R1_IDLE_STATE: 80 | break 81 | else: 82 | raise OSError("no SD card") 83 | 84 | # CMD8: determine card version 85 | r = self.cmd(8, 0x01AA, 0x87, 4) 86 | if r == _R1_IDLE_STATE: 87 | self.init_card_v2() 88 | elif r == (_R1_IDLE_STATE | _R1_ILLEGAL_COMMAND): 89 | self.init_card_v1() 90 | else: 91 | raise OSError("couldn't determine SD card version") 92 | 93 | # get the number of sectors 94 | # CMD9: response R2 (R1 byte + 16-byte block read) 95 | if self.cmd(9, 0, 0, 0, False) != 0: 96 | raise OSError("no response from SD card") 97 | csd = bytearray(16) 98 | self.readinto(csd) 99 | if csd[0] & 0xC0 == 0x40: # CSD version 2.0 100 | self.sectors = ((csd[8] << 8 | csd[9]) + 1) * 1024 101 | elif csd[0] & 0xC0 == 0x00: # CSD version 1.0 (old, <=2GB) 102 | c_size = csd[6] & 0b11 | csd[7] << 2 | (csd[8] & 0b11000000) << 4 103 | c_size_mult = ((csd[9] & 0b11) << 1) | csd[10] >> 7 104 | self.sectors = (c_size + 1) * (2 ** (c_size_mult + 2)) 105 | else: 106 | raise OSError("SD card CSD format not supported") 107 | # print('sectors', self.sectors) 108 | 109 | # CMD16: set block length to 512 bytes 110 | if self.cmd(16, 512, 0) != 0: 111 | raise OSError("can't set 512 block size") 112 | 113 | # set to high data rate now that it's initialised 114 | self.init_spi(1320000) 115 | 116 | def init_card_v1(self): 117 | for i in range(_CMD_TIMEOUT): 118 | self.cmd(55, 0, 0) 119 | if self.cmd(41, 0, 0) == 0: 120 | self.cdv = 512 121 | # print("[SDCard] v1 card") 122 | return 123 | raise OSError("timeout waiting for v1 card") 124 | 125 | def init_card_v2(self): 126 | for i in range(_CMD_TIMEOUT): 127 | time.sleep_ms(50) 128 | self.cmd(58, 0, 0, 4) 129 | self.cmd(55, 0, 0) 130 | if self.cmd(41, 0x40000000, 0) == 0: 131 | self.cmd(58, 0, 0, 4) 132 | self.cdv = 1 133 | # print("[SDCard] v2 card") 134 | return 135 | raise OSError("timeout waiting for v2 card") 136 | 137 | def cmd(self, cmd, arg, crc, final=0, release=True, skip1=False): 138 | self.cs(0) 139 | 140 | # create and send the command 141 | buf = self.cmdbuf 142 | buf[0] = 0x40 | cmd 143 | buf[1] = arg >> 24 144 | buf[2] = arg >> 16 145 | buf[3] = arg >> 8 146 | buf[4] = arg 147 | buf[5] = crc 148 | self.spi.write(buf) 149 | 150 | if skip1: 151 | self.spi.readinto(self.tokenbuf, 0xFF) 152 | 153 | # wait for the response (response[7] == 0) 154 | for i in range(_CMD_TIMEOUT): 155 | self.spi.readinto(self.tokenbuf, 0xFF) 156 | response = self.tokenbuf[0] 157 | if not (response & 0x80): 158 | # this could be a big-endian integer that we are getting here 159 | for j in range(final): 160 | self.spi.write(b"\xff") 161 | if release: 162 | self.cs(1) 163 | self.spi.write(b"\xff") 164 | return response 165 | 166 | # timeout 167 | self.cs(1) 168 | self.spi.write(b"\xff") 169 | return -1 170 | 171 | def readinto(self, buf): 172 | self.cs(0) 173 | 174 | # read until start byte (0xff) 175 | for i in range(_CMD_TIMEOUT): 176 | self.spi.readinto(self.tokenbuf, 0xFF) 177 | if self.tokenbuf[0] == _TOKEN_DATA: 178 | break 179 | else: 180 | self.cs(1) 181 | raise OSError("timeout waiting for response") 182 | 183 | # read data 184 | mv = self.dummybuf_memoryview 185 | if len(buf) != len(mv): 186 | mv = mv[: len(buf)] 187 | self.spi.write_readinto(mv, buf) 188 | 189 | # read checksum 190 | self.spi.write(b"\xff") 191 | self.spi.write(b"\xff") 192 | 193 | self.cs(1) 194 | self.spi.write(b"\xff") 195 | 196 | def write(self, token, buf): 197 | self.cs(0) 198 | 199 | # send: start of block, data, checksum 200 | self.spi.read(1, token) 201 | self.spi.write(buf) 202 | self.spi.write(b"\xff") 203 | self.spi.write(b"\xff") 204 | 205 | # check the response 206 | if (self.spi.read(1, 0xFF)[0] & 0x1F) != 0x05: 207 | self.cs(1) 208 | self.spi.write(b"\xff") 209 | return 210 | 211 | # wait for write to finish 212 | while self.spi.read(1, 0xFF)[0] == 0: 213 | pass 214 | 215 | self.cs(1) 216 | self.spi.write(b"\xff") 217 | 218 | def write_token(self, token): 219 | self.cs(0) 220 | self.spi.read(1, token) 221 | self.spi.write(b"\xff") 222 | # wait for write to finish 223 | while self.spi.read(1, 0xFF)[0] == 0x00: 224 | pass 225 | 226 | self.cs(1) 227 | self.spi.write(b"\xff") 228 | 229 | def readblocks(self, block_num, buf): 230 | nblocks = len(buf) // 512 231 | assert nblocks and not len(buf) % 512, "Buffer length is invalid" 232 | if nblocks == 1: 233 | # CMD17: set read address for single block 234 | if self.cmd(17, block_num * self.cdv, 0, release=False) != 0: 235 | # release the card 236 | self.cs(1) 237 | raise OSError(5) # EIO 238 | # receive the data and release card 239 | self.readinto(buf) 240 | else: 241 | # CMD18: set read address for multiple blocks 242 | if self.cmd(18, block_num * self.cdv, 0, release=False) != 0: 243 | # release the card 244 | self.cs(1) 245 | raise OSError(5) # EIO 246 | offset = 0 247 | mv = memoryview(buf) 248 | while nblocks: 249 | # receive the data and release card 250 | self.readinto(mv[offset : offset + 512]) 251 | offset += 512 252 | nblocks -= 1 253 | if self.cmd(12, 0, 0xFF, skip1=True): 254 | raise OSError(5) # EIO 255 | 256 | def writeblocks(self, block_num, buf): 257 | nblocks, err = divmod(len(buf), 512) 258 | assert nblocks and not err, "Buffer length is invalid" 259 | if nblocks == 1: 260 | # CMD24: set write address for single block 261 | if self.cmd(24, block_num * self.cdv, 0) != 0: 262 | raise OSError(5) # EIO 263 | 264 | # send the data 265 | self.write(_TOKEN_DATA, buf) 266 | else: 267 | # CMD25: set write address for first block 268 | if self.cmd(25, block_num * self.cdv, 0) != 0: 269 | raise OSError(5) # EIO 270 | # send the data 271 | offset = 0 272 | mv = memoryview(buf) 273 | while nblocks: 274 | self.write(_TOKEN_CMD25, mv[offset : offset + 512]) 275 | offset += 512 276 | nblocks -= 1 277 | self.write_token(_TOKEN_STOP_TRAN) 278 | 279 | def ioctl(self, op, arg): 280 | if op == 4: # get number of blocks 281 | return self.sectors 282 | -------------------------------------------------------------------------------- /old-src/micropython_code/workSpace/sdread.py: -------------------------------------------------------------------------------- 1 | import os, sdcard 2 | from machine import Pin, SPI, reset 3 | 4 | def init_SD(): 5 | spi = SPI(2, baudrate = 10000000, polarity = 0, phase = 0, bits = 8, firstbit = SPI.MSB, 6 | sck = Pin(18, Pin.OUT, Pin.PULL_DOWN), 7 | mosi = Pin(23, Pin.OUT, Pin.PULL_UP), 8 | miso = Pin(19, Pin.IN, Pin.PULL_UP)) 9 | 10 | spi.init() # Ensure right baudrate 11 | sd = sdcard.SDCard(spi, Pin(22)) # Compatible with PCB 12 | return sd 13 | 14 | def mount(sd): 15 | vfs = os.VfsFat(sd) 16 | os.mount(vfs, "/sd") 17 | print("Already mount") 18 | 19 | def umount(): 20 | os.umount("/sd") 21 | print("Already umount") 22 | 23 | def get_wav_list(sd): 24 | 25 | file_list = os.listdir("/sd") 26 | print(file_list) 27 | wav_list = [] 28 | for name in file_list: 29 | if name[-4:] is ".wav": 30 | wav_list.append(name) 31 | 32 | print(wav_list) 33 | return wav_list -------------------------------------------------------------------------------- /old-src/micropython_code/workSpace/sdtest.py: -------------------------------------------------------------------------------- 1 | # Test for sdcard block protocol 2 | # Peter hinch 30th Jan 2016 3 | import os, sdcard 4 | from machine import Pin, SPI, reset 5 | 6 | 7 | def sdtest(): 8 | print("1") 9 | 10 | #hardware spi 11 | 12 | spi = SPI(2, baudrate = 10000000, polarity = 0, phase = 0, bits = 8, firstbit = SPI.MSB, 13 | sck = Pin(18, Pin.OUT, Pin.PULL_DOWN), 14 | mosi = Pin(23, Pin.OUT, Pin.PULL_UP), 15 | miso = Pin(19, Pin.IN, Pin.PULL_UP)) 16 | 17 | 18 | 19 | spi.init() # Ensure right baudrate 20 | sd = sdcard.SDCard(spi, Pin(22)) # Compatible with PCB 21 | vfs = os.VfsFat(sd) 22 | os.mount(vfs, "/fc") 23 | print("Filesystem check") 24 | print(os.listdir("/fc")) 25 | 26 | print("1") 27 | 28 | line = "abcdefghijklmnopqrstuvwxyz\n" 29 | lines = line * 200 # 5400 chars 30 | short = "1234567890\n" 31 | 32 | print("1") 33 | 34 | fn = "/fc/rats.txt" 35 | print() 36 | print("Multiple block read/write") 37 | with open(fn, "w") as f: 38 | n = f.write(lines) 39 | print(n, "bytes written") 40 | n = f.write(short) 41 | print(n, "bytes written") 42 | n = f.write(lines) 43 | print(n, "bytes written") 44 | 45 | with open(fn, "r") as f: 46 | result1 = f.read() 47 | print(len(result1), "bytes read") 48 | 49 | fn = "/fc/rats1.txt" 50 | print() 51 | print("Single block read/write") 52 | with open(fn, "w") as f: 53 | n = f.write(short) # one block 54 | print(n, "bytes written") 55 | 56 | with open(fn, "r") as f: 57 | result2 = f.read() 58 | print(len(result2), "bytes read") 59 | 60 | os.umount("/fc") 61 | 62 | print() 63 | print("Verifying data read back") 64 | success = True 65 | if result1 == "".join((lines, short, lines)): 66 | print("Large file Pass") 67 | else: 68 | print("Large file Fail") 69 | success = False 70 | if result2 == short: 71 | print("Small file Pass") 72 | else: 73 | print("Small file Fail") 74 | success = False 75 | print() 76 | print("Tests", "passed" if success else "failed") 77 | 78 | 79 | -------------------------------------------------------------------------------- /old-src/micropython_code/workSpace/ssd1306.py: -------------------------------------------------------------------------------- 1 | 2 | # MicroPython SSD1306 OLED driver, I2C and SPI interfaces 3 | 4 | from micropython import const 5 | import time 6 | import framebuf 7 | 8 | 9 | # register definitions 10 | SET_CONTRAST = const(0x81) 11 | SET_ENTIRE_ON = const(0xa4) 12 | SET_NORM_INV = const(0xa6) 13 | SET_DISP = const(0xae) 14 | SET_MEM_ADDR = const(0x20) 15 | SET_COL_ADDR = const(0x21) 16 | SET_PAGE_ADDR = const(0x22) 17 | SET_DISP_START_LINE = const(0x40) 18 | SET_SEG_REMAP = const(0xa0) 19 | SET_MUX_RATIO = const(0xa8) 20 | SET_COM_OUT_DIR = const(0xc0) 21 | SET_DISP_OFFSET = const(0xd3) 22 | SET_COM_PIN_CFG = const(0xda) 23 | SET_DISP_CLK_DIV = const(0xd5) 24 | SET_PRECHARGE = const(0xd9) 25 | SET_VCOM_DESEL = const(0xdb) 26 | SET_CHARGE_PUMP = const(0x8d) 27 | 28 | 29 | class SSD1306: 30 | def __init__(self, width, height, external_vcc): 31 | self.width = width 32 | self.height = height 33 | self.external_vcc = external_vcc 34 | self.pages = self.height // 8 35 | self.buffer = bytearray(self.pages * self.width) 36 | fb = framebuf.FrameBuffer(self.buffer, self.width, self.height, framebuf.MONO_VLSB) 37 | self.framebuf = fb 38 | # Provide methods for accessing FrameBuffer graphics primitives. This is a 39 | # workround because inheritance from a native class is currently unsupported. 40 | # http://docs.micropython.org/en/latest/pyboard/library/framebuf.html 41 | self.fill = fb.fill 42 | self.pixel = fb.pixel 43 | self.hline = fb.hline 44 | self.vline = fb.vline 45 | self.line = fb.line 46 | self.rect = fb.rect 47 | self.fill_rect = fb.fill_rect 48 | self.text = fb.text 49 | self.scroll = fb.scroll 50 | self.blit = fb.blit 51 | self.poweron() 52 | self.init_display() 53 | 54 | def init_display(self): 55 | for cmd in ( 56 | SET_DISP | 0x00, # off 57 | # address setting 58 | SET_MEM_ADDR, 0x00, # horizontal 59 | # resolution and layout 60 | SET_DISP_START_LINE | 0x00, 61 | SET_SEG_REMAP | 0x01, # column addr 127 mapped to SEG0 62 | SET_MUX_RATIO, self.height - 1, 63 | SET_COM_OUT_DIR | 0x08, # scan from COM[N] to COM0 64 | SET_DISP_OFFSET, 0x00, 65 | SET_COM_PIN_CFG, 0x02 if self.height == 32 else 0x12, 66 | # timing and driving scheme 67 | SET_DISP_CLK_DIV, 0x80, 68 | SET_PRECHARGE, 0x22 if self.external_vcc else 0xf1, 69 | SET_VCOM_DESEL, 0x30, # 0.83*Vcc 70 | # display 71 | SET_CONTRAST, 0xff, # maximum 72 | SET_ENTIRE_ON, # output follows RAM contents 73 | SET_NORM_INV, # not inverted 74 | # charge pump 75 | SET_CHARGE_PUMP, 0x10 if self.external_vcc else 0x14, 76 | SET_DISP | 0x01): # on 77 | self.write_cmd(cmd) 78 | self.fill(0) 79 | self.show() 80 | 81 | def poweroff(self): 82 | self.write_cmd(SET_DISP | 0x00) 83 | 84 | def contrast(self, contrast): 85 | self.write_cmd(SET_CONTRAST) 86 | self.write_cmd(contrast) 87 | 88 | def invert(self, invert): 89 | self.write_cmd(SET_NORM_INV | (invert & 1)) 90 | 91 | def show(self): 92 | x0 = 0 93 | x1 = self.width - 1 94 | if self.width == 64: 95 | # displays with width of 64 pixels are shifted by 32 96 | x0 += 32 97 | x1 += 32 98 | self.write_cmd(SET_COL_ADDR) 99 | self.write_cmd(x0) 100 | self.write_cmd(x1) 101 | self.write_cmd(SET_PAGE_ADDR) 102 | self.write_cmd(0) 103 | self.write_cmd(self.pages - 1) 104 | self.write_data(self.buffer) 105 | 106 | 107 | class SSD1306_I2C(SSD1306): 108 | def __init__(self, width, height, i2c, addr=0x3c, external_vcc=False): 109 | self.i2c = i2c 110 | self.addr = addr 111 | self.temp = bytearray(2) 112 | super().__init__(width, height, external_vcc) 113 | 114 | def write_cmd(self, cmd): 115 | self.temp[0] = 0x80 # Co=1, D/C#=0 116 | self.temp[1] = cmd 117 | self.i2c.writeto(self.addr, self.temp) 118 | 119 | def write_data(self, buf): 120 | self.temp[0] = self.addr << 1 121 | self.temp[1] = 0x40 # Co=0, D/C#=1 122 | self.i2c.start() 123 | self.i2c.write(self.temp) 124 | self.i2c.write(buf) 125 | self.i2c.stop() 126 | 127 | def poweron(self): 128 | pass 129 | 130 | 131 | class SSD1306_SPI(SSD1306): 132 | def __init__(self, width, height, spi, dc, res, cs, external_vcc=False): 133 | self.rate = 10 * 1024 * 1024 134 | dc.init(dc.OUT, value=0) 135 | res.init(res.OUT, value=0) 136 | cs.init(cs.OUT, value=1) 137 | self.spi = spi 138 | self.dc = dc 139 | self.res = res 140 | self.cs = cs 141 | super().__init__(width, height, external_vcc) 142 | 143 | def write_cmd(self, cmd): 144 | self.spi.init(baudrate=self.rate, polarity=0, phase=0) 145 | self.cs(1) 146 | self.dc(0) 147 | self.cs(0) 148 | self.spi.write(bytearray([cmd])) 149 | self.cs(1) 150 | 151 | def write_data(self, buf): 152 | self.spi.init(baudrate=self.rate, polarity=0, phase=0) 153 | self.cs(1) 154 | self.dc(1) 155 | self.cs(0) 156 | self.spi.write(buf) 157 | self.cs(1) 158 | 159 | def poweron(self): 160 | self.res(1) 161 | time.sleep_ms(1) 162 | self.res(0) 163 | time.sleep_ms(10) 164 | self.res(1) 165 | 166 | 167 | -------------------------------------------------------------------------------- /old-src/micropython_code/workSpace/test.py: -------------------------------------------------------------------------------- 1 | 2 | import sdread 3 | import sdtest 4 | import test2 5 | import display_ssd1306_i2c 6 | from machine import Pin 7 | import time 8 | 9 | Pin_up = Pin(39,Pin.IN,Pin.PULL_UP) 10 | Pin_down = Pin(36,Pin.IN,Pin.PULL_UP) 11 | Pin_play = Pin(35,Pin.IN,Pin.PULL_UP) 12 | 13 | def music_list_show(lcd,wav_list,index): 14 | lcd.clear() 15 | 16 | if index - 2 >= 0: 17 | lcd.show_text(wav_list[index - 2],0,0,False,False) 18 | 19 | if index - 1 >= 0: 20 | lcd.show_text(wav_list[index - 1],0,12,False,False) 21 | 22 | lcd.show_text(wav_list[index],0,24,False,False) 23 | 24 | if index + 1 < len(wav_list): 25 | lcd.show_text(wav_list[index + 1],0,36,False,False) 26 | 27 | if index + 2 < len(wav_list): 28 | lcd.show_text(wav_list[index + 2],0,48,False,False) 29 | 30 | lcd.display.line(0,22,127,22,1) 31 | lcd.display.line(0,34,127,34,1) 32 | lcd.show() 33 | 34 | 35 | def main(): 36 | 37 | lcd = display_ssd1306_i2c.Display() 38 | 39 | sd = sdread.init_SD() 40 | sdread.mount(sd) 41 | wav_list = sdread.get_wav_list(sd) 42 | index = 0 43 | last_index = -1 44 | play_status = 0 45 | 46 | while True: 47 | pass 48 | if Pin_up.value() == 0 : 49 | print("up") 50 | if index > 0: 51 | index -= 1 52 | if Pin_down.value() == 0 : 53 | print("down") 54 | if index < len(wav_list) - 1: 55 | index += 1 56 | if Pin_play.value() == 0 : 57 | print("play") 58 | play_status = 1 59 | 60 | if index is not last_index: 61 | music_list_show(lcd,wav_list,index) 62 | last_index = index 63 | 64 | time.sleep(0.5) 65 | 66 | if play_status == 1: 67 | test2.music(Pin_play,wav_list[index]) 68 | play_status = 0 69 | time.sleep(0.5) 70 | 71 | 72 | 73 | 74 | sdread.umount() 75 | 76 | #test2.music() 77 | pass 78 | 79 | if __name__ == '__main__': 80 | main() 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /old-src/micropython_code/workSpace/test2.py: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | # Copyright (c) 2020 Mike Teachman 3 | # https://opensource.org/licenses/MIT 4 | 5 | # Purpose: 6 | # - read 16-bit audio samples from a mono formatted WAV file on SD card 7 | # - write audio samples to an I2S amplifier or DAC module 8 | # 9 | # Sample WAV files in wav_files folder: 10 | # "taunt-16k-16bits-mono.wav" 11 | # "taunt-16k-16bits-mono-12db.wav" (lower volume version) 12 | # 13 | # Hardware tested: 14 | # - MAX98357A amplifier module (Adafruit I2S 3W Class D Amplifier Breakout) 15 | # - PCM5102 stereo DAC module 16 | # 17 | # The WAV file will play continuously until a keyboard interrupt is detected or 18 | # the ESP32 is reset 19 | 20 | from machine import I2S 21 | import sdcard 22 | from machine import Pin 23 | from machine import SPI 24 | import uos 25 | 26 | def music(Pin_play,wav_name): 27 | #======= USER CONFIGURATION ======= 28 | #WAV_FILE = 'iveryhappy44100Hz.wav' 29 | WAV_FILE = wav_name 30 | SAMPLE_RATE_IN_HZ = 44100 31 | #======= USER CONFIGURATION ======= 32 | 33 | bck_pin = Pin(26) 34 | ws_pin = Pin(25) 35 | sdout_pin = Pin(27) 36 | 37 | # channelformat settings: 38 | # mono WAV: channelformat=I2S.ONLY_LEFT 39 | audio_out = I2S( 40 | I2S.NUM0, 41 | bck=bck_pin, ws=ws_pin, sdout=sdout_pin, 42 | standard=I2S.PHILIPS, 43 | mode=I2S.MASTER_TX, 44 | dataformat=I2S.B16, 45 | channelformat=I2S.ONLY_LEFT, 46 | samplerate=SAMPLE_RATE_IN_HZ, 47 | dmacount=10, dmalen=512) 48 | 49 | wav_file = '/sd/{}'.format(WAV_FILE) 50 | wav = open(wav_file,'rb') 51 | 52 | # advance to first byte of Data section in WAV file 53 | pos = wav.seek(44) 54 | 55 | # allocate sample arrays 56 | # memoryview used to reduce heap allocation in while loop 57 | wav_samples = bytearray(2048) 58 | wav_samples_mv = memoryview(wav_samples) 59 | 60 | print('Starting') 61 | # continuously read audio samples from the WAV file 62 | # and write them to an I2S DAC 63 | while True: 64 | try: 65 | num_read = wav.readinto(wav_samples_mv) 66 | 67 | """ 68 | for i in range(len(wav_samples_mv)): 69 | wav_samples_mv[i] = int(wav_samples_mv[i]/2) 70 | #wav_samples_mv[i] =wav_samples_mv[i] + int ((128 - wav_samples_mv[i]) / 2) 71 | pass 72 | """ 73 | 74 | num_written = 0 75 | # end of WAV file? 76 | if num_read == 0: 77 | # advance to first byte of Data section 78 | pos = wav.seek(44) 79 | else: 80 | # loop until all samples are written to the I2S peripheral 81 | while num_written < num_read: 82 | num_written += audio_out.write(wav_samples_mv[num_written:num_read], timeout=0) 83 | if Pin_play.value() == 0: 84 | wav.close() 85 | audio_out.deinit() 86 | print('Hand Out') 87 | return 88 | except (KeyboardInterrupt, Exception) as e: 89 | print('caught exception {} {}'.format(type(e).__name__, e)) 90 | break 91 | 92 | wav.close() 93 | audio_out.deinit() 94 | print('Auto Out') 95 | return 96 | 97 | 98 | 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /old-src/micropython_code/workSpace/test3.py: -------------------------------------------------------------------------------- 1 | import music 2 | 3 | 4 | def main(): 5 | wav_player = music.Music() 6 | wav_player.SDcard_init() 7 | while True: 8 | if wav_player.index is not wav_player.last_index: 9 | wav_player.Display_list() 10 | wav_player.index = wav_player.last_index 11 | 12 | wav_player.Keyboard_scanf() 13 | 14 | if wav_player.play_status == 1: 15 | wav_player.Audio_init() 16 | wav_player.Audio_play() 17 | wav_player.Audio_close() 18 | 19 | 20 | if __name__ == '__main__': 21 | main() 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /readme-oldversion.md: -------------------------------------------------------------------------------- 1 | # MicroPython Audio WavPlayer 2 | 3 | ```c++ 4 | /* 5 | Version: V1.1 6 | Author: Vincent 7 | Create Date: 2020/7/8 8 | Note: 9 | 2020/7/18 V1.1: 10 | 1,Move the original WavPlayer to "\Project_MakePython_Audio_Music\ ESP32_wav_player" 11 | 2,"\Project_MakePython_Audio_Music\ ESP32_MP3" folder for Mp3 decoding instance and volume control instance. 12 | 3,Added a brief description of the MP3 decoder and how to install the library. 13 | 4. MicroPython Audio can be downloaded without unplugging. When uploading the program, please rotate the switch next to the 3.5mm Audio interface to the Audio socket. 14 | */ 15 | ``` 16 | 17 | [YOUTUBE:MakePython Audio Music Play](https://www.youtube.com/watch?v=0urJ_uxfW0k&feature=youtu.be) 18 | ![main](md_pic/main.JPG) 19 | 20 | [toc] 21 | 22 | # OVERVIEW 23 | 24 | ## Intruduce 25 | 26 | [Makerfabs home page](https://www.makerfabs.com/) 27 | 28 | [Makerfabs Wiki](https://makerfabs.com/wiki/index.php?title=Main_Page) 29 | 30 | MakePython Audio inherited the DAC chip and SD card module.The I2S chip allows you to play waV songs stored on an SD card without decoding.The SSD1306 screen displays basic information about the song, and the scroll wheel switch on Audio allows you to switch and pause the music. 31 | 32 | 33 | 34 | ![oversee](md_pic/oversee.png) 35 | 36 | ## Equipment list 37 | 38 | - [MakePython ESP32](https://www.makerfabs.com/wiki/index.php?title=MakePython_ESP32) 39 | - [MakaPython Audio](https://www.makerfabs.com/wiki/index.php?title=MakaPython_Audio) 40 | - Audio/headphones with 3.5mm audio connector 41 | - Micro SD card 42 | 43 | 44 | 45 | # STEPS 46 | 47 | ## Install ESP32 board 48 | 49 | - Open arduino ide. 50 | - Select Tools/Board/BoardsManager. 51 | - Search esp32. 52 | - Install esp32 by Espressif Systems. 53 | 54 | ![image-20200708115047882](md_pic/image-20200708115047882.png) 55 | 56 | ## Install libraries 57 | 58 | - Open arduino ide. 59 | - Select Tools/Manage Libraries. 60 | - Search ssd1306. 61 | 62 | - Install Adafruit SSD1306 by Adafruit. 63 | 64 | - If youer ardino ide version is old,maybe can't auto install dependent libraries, likes Adafruit_GFX.You may manual install or upgrade arduino ide, such as 1.8.13. 65 | 66 | 67 | 68 | ![image-20200708115545998](md_pic/image-20200708115545998.png) 69 | 70 | ## Burn ESP32 71 | 72 | - Open file "/esp32_wav_player/esp32_wav_player.ino" 73 | 74 | - Select Toos/board/Esp32 Dev Modue. 75 | 76 | ![image-20200708120243416](md_pic/image-20200708120243416.png) 77 | 78 | - Connect ESP32 to your PC via Micro USB . 79 | - Select Port. 80 | - And at last ,push upload. 81 | - **ATTENTION !!! Plug ESP32 and Audio expansion boards together after burning. Be sure to plug them together after burning or the firmware will not burn.** 82 | - **V1.1 Add:** MicroPython Audio can be downloaded without unplugging. When uploading the program, please rotate the switch next to the 3.5mm Audio interface to the Audio socket. 83 | 84 | ![Without_plug](md_pic/Without_plug.png) 85 | 86 | ## Prepare Music 87 | 88 | - Add some wav music in sdcard.Of course ,name must be English. 89 | - This example program can decode only 44.1khz, 16bit, stereo WAV files.This is a common file format for songs on the Internet.But the I2S chip itself supports waV in all common formats, such as sampling rate of 22.05khz, 16kHz, 24bit, 16bit, mono channel, etc.If you want to play music in other format, please modify the code yourself. 90 | - Insert a Micro SD card into MakePython Audio. 91 | - Plug the stereo or earphone into a 3.5mm audio jack. 92 | 93 | ![3.5mm](md_pic/3.5mm.JPG) 94 | 95 | 96 | 97 | ## How to use WavPlayer 98 | 99 | - Power the ESP32 via Micro USB and the LCD screen displays the basic information of the song. 100 | 101 | ![image-20200708134131231](md_pic/music_info.JPG) 102 | 103 | - Use the switch on the left to control the music.Flip up and switch to the previous song.Scroll down and switch to the next song.Press inward to pause/continue the play. 104 | 105 | ![image-20200708134131231](md_pic/image-20200708134131231.png) 106 | 107 | # Arduino Code Explain 108 | 109 | ```c++ 110 | Wire.begin(MAKEPYTHON_ESP32_SDA, MAKEPYTHON_ESP32_SCL); 111 | // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally 112 | if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) 113 | { // Address 0x3C for 128x32 114 | Serial.println(F("SSD1306 allocation failed")); 115 | for (;;) 116 | ; // Don't proceed, loop forever 117 | } 118 | ``` 119 | 120 | - Set the I2C pin of MakePython ESP32 to drive the LCD. 121 | 122 | ```c++ 123 | SPI.begin(18, 19, 23, 5); 124 | if (!SD.begin(22, SPI)) 125 | { 126 | Serial.println("Card Mount Failed"); 127 | return; 128 | } 129 | ``` 130 | 131 | - Set the SPI pin of MakePython ESP32 to drive the SD card module. 132 | ```c++ 133 | music_num = get_wav_list(SD, "/", 0, music_list); 134 | ``` 135 | - Gets a list of WAV files in the SD card. 136 | 137 | ```c++ 138 | music_num = get_wav_list(SD, "/", 0, music_list); 139 | ``` 140 | - Send audio signals like DAC chips through I2S interface. 141 | 142 | ```c++ 143 | while (file.readBytes(data, sizeof(data))) 144 | { 145 | I2S_Write(data, sizeof(data)); 146 | } 147 | ``` 148 | 149 | # MP3 Decoder 150 | 151 | ## Introduce 152 | 153 | UDA1334ATS on Makepython Audio does not support MP3 hardware decoding. Here is an example of MP3 decoding and volume control.Not only can you read MP3 files from your SD card, but you can also play MP3 stations directly from the Internet. 154 | 155 | ## Install Library 156 | 157 | Lib from github:[schreibfaul1/ESP32-audioI2S](https://github.com/schreibfaul1/ESP32-audioI2S/) 158 | 159 | You can download the library folder "C:\Users\ YourName\Documents\Arduino\ Libraries" installed into the Arduino compiler.Or There is also a copy in the folder "\Project_MakePython_Audio_Music\esp32_mp3\". 160 | 161 | ## Run Example 162 | 163 | - Change the file name of the MP3 in SD card which you want to play. 164 | 165 | ```c++ 166 | // audio.connecttoFS(SD, "/320k_test.mp3"); 167 | audio.connecttoFS(SD, "/MoonlightBay.mp3");//ChildhoodMemory.mp3 //MoonRiver.mp3 168 | // audio.connecttoFS(SD, "test.wav"); 169 | // audio.connecttohost("http://www.wdr.de/wdrlive/media/einslive.m3u"); 170 | // audio.connecttohost("http://macslons-irish-pub-radio.com/media.asx"); 171 | // audio.connecttohost("http://mp3.ffh.de/radioffh/hqlivestream.aac"); // 128k aac 172 | // audio.connecttohost("http://mp3.ffh.de/radioffh/hqlivestream.mp3"); // 128k mp3 173 | // audio.connecttospeech("Wenn die Hunde schlafen, kann der Wolf gut Schafe stehlen.", "de"); 174 | ``` 175 | 176 | - Save and then upload the code to ESP32. 177 | - Plug the SD card into ESP32 and the 3.5mm Audio plug into the Audio interface of MakePython Audio. 178 | - Press RST to restart ESP32 to play music. 179 | 180 | 181 | 182 | # Other Files 183 | 184 | - Folder:"/esp32_sdteset","/esp32_ssd1306test","/esp32_i2stest".They're all testing demos. 185 | - Code in "/workSpace" is a python demo.But playing 44.1khz, 16bit, stereo WAV has noise, the rest of the format can play, you can try. 186 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # MicroPython Audio MusicPlayer 2 | 3 | ```c++ 4 | /* 5 | Version: V2.1 6 | Author: Vincent 7 | Create Date: 2020/7/8 8 | Update Date: 2020/9/11 9 | Note: 10 | 2020/9/11 V2.1: 11 | 1,Add a bluetooth stero demo. 12 | 2020/7/29 V2.0: 13 | 1,The new version supports all the functions of MP3: song switching, volume adjustment, pause and mute.Support mp3, WAV, ACC common formats. 14 | 2,3D printing shells designed for MakePython ESP32 and MakePython Audio are provided. 15 | 3,The code was completely refacted, and the files of V1.1 were placed in the old-SRc folder. The previous README was renamed to Readme-OldVersion. 16 | 2020/7/18 V1.1: 17 | 1,Move the original WavPlayer to "\Project_MakePython_Audio_Music\ ESP32_wav_player" 18 | 2,"\Project_MakePython_Audio_Music\ ESP32_MP3" folder for Mp3 decoding instance and volume control instance. 19 | 3,Added a brief description of the MP3 decoder and how to install the library. 20 | 4. MicroPython Audio can be downloaded without unplugging. When uploading the program, please rotate the switch next to the 3.5mm Audio interface to the Audio socket. 21 | */ 22 | ``` 23 | [YOUTUBE:How to DIY an ESP32 Audio Player(3D print box)](https://youtu.be/uyHbnU4p6tc) 24 | 25 | [YOUTUBE:MakePython Audio Music Play](https://www.youtube.com/watch?v=0urJ_uxfW0k&feature=youtu.be) 26 | ![main](md_pic/main.JPG) 27 | 28 | [toc] 29 | 30 | # OVERVIEW 31 | 32 | ## Intruduce 33 | 34 | [Makerfabs home page](https://www.makerfabs.com/) 35 | 36 | [Makerfabs Wiki](https://wiki.makerfabs.com/) 37 | 38 | MakePython Audio inherited the DAC chip and SD card module.The I2S chip allows you to play songs stored on an SD card .The SSD1306 screen displays basic information about the song, and the scroll wheel switch on Audio allows you to switch and pause the music. 39 | 40 | 41 | 42 | ![oversee](md_pic/oversee2.png) 43 | 44 | ## Equipment list 45 | 46 | - [MakePython ESP32](https://wiki.makerfabs.com/MaESP_ESP32.html) 47 | - [MakaPython Audio](https://wiki.makerfabs.com/MaESP_Audio.html) 48 | - Audio/headphones with 3.5mm audio connector 49 | - Micro SD card 50 | 51 | 52 | 53 | # STEPS 54 | 55 | ## Prepare And Burn 56 | 57 | **If you have any questions,such as how to install the development board, how to download the code, how to install the library. Please refer to :[Makerfabs_FAQ](https://github.com/Makerfabs/Makerfabs_FAQ)** 58 | 59 | - Install board : esp32 . 60 | 61 | - Install library : Adafruit SSD1306 and dependent libraries. 62 | - Install zip library : [ESP32-audioI2S](https://github.com/schreibfaul1/ESP32-audioI2S)("Audio.h") 63 | 64 | - Upload file "/Project_MakePython_Audio_Music/music_player.ino" 65 | 66 | 67 | - **~~ATTENTION !!! Plug ESP32 and Audio expansion boards together after burning. Be sure to plug them together after burning or the firmware will not burn.~~** 68 | - **V1.1 Add: MicroPython Audio can be downloaded without unplugging. When uploading the program, please rotate the switch next to the 3.5mm Audio interface to the Audio socket.** 69 | 70 | ![Without_plug](md_pic/Without_plug.png) 71 | 72 | ## Prepare Music 73 | 74 | - Add some music(.mp3 or .wav) in sdcard.Of course ,name must be English. 75 | - Insert a Micro SD card into MakePython Audio. 76 | - Plug the stereo or earphone into a 3.5mm audio jack. 77 | 78 | ![3.5mm](md_pic/3.5mm.JPG) 79 | 80 | 81 | 82 | ## How to use MusicPlayer 83 | 84 | - Power the ESP32 via Micro USB and the LCD screen displays the basic information of the song. 85 | - Such as :The name of the song, the time played, the length of the song. 86 | 87 | ![image-20200708134131231](md_pic/music_info.JPG) 88 | 89 | - Lower side switch, left and right for next song, Previous.Press inward to pause. 90 | - The switch on the left, volume up and down.Press in to mute. 91 | 92 | ![image-20200708134131231](md_pic/button_control.png) 93 | 94 | 95 | # Esp32-AudioI2S Lib 96 | 97 | ## Introduce 98 | 99 | UDA1334ATS on Makepython Audio does not support MP3 hardware decoding. Here is an example of MP3 decoding and volume control.Not only can you read MP3 files from your SD card, but you can also play MP3 stations directly from the Internet. 100 | 101 | ## Install Library 102 | 103 | Lib from github:[schreibfaul1/ESP32-audioI2S](https://github.com/schreibfaul1/ESP32-audioI2S/) 104 | 105 | You can download the library folder "C:\Users\ YourName\Documents\Arduino\ Libraries" installed into the Arduino compiler.Or There is also a copy in the folder "\Project_MakePython_Audio_Music\esp32_mp3\". 106 | 107 | ## Run Example 108 | 109 | - Change the file name of the MP3 in SD card which you want to play. 110 | 111 | ```c++ 112 | // audio.connecttoFS(SD, "/320k_test.mp3"); 113 | audio.connecttoFS(SD, "/MoonlightBay.mp3");//ChildhoodMemory.mp3 //MoonRiver.mp3 114 | // audio.connecttoFS(SD, "test.wav"); 115 | // audio.connecttohost("http://www.wdr.de/wdrlive/media/einslive.m3u"); 116 | // audio.connecttohost("http://macslons-irish-pub-radio.com/media.asx"); 117 | // audio.connecttohost("http://mp3.ffh.de/radioffh/hqlivestream.aac"); // 128k aac 118 | // audio.connecttohost("http://mp3.ffh.de/radioffh/hqlivestream.mp3"); // 128k mp3 119 | // audio.connecttospeech("Wenn die Hunde schlafen, kann der Wolf gut Schafe stehlen.", "de"); 120 | ``` 121 | 122 | - Save and then upload the code to ESP32. 123 | - Plug the SD card into ESP32 and the 3.5mm Audio plug into the Audio interface of MakePython Audio. 124 | - Press RST to restart ESP32 to play music. 125 | 126 | 127 | 128 | # 3D Printer Box 129 | 130 | We designed a simple 3D-printed case. Don't need support. 131 | 132 | ![3d1](md_pic/3d1.png) 133 | 134 | ![3d1](md_pic/3d2.png) 135 | 136 | # Old Files 137 | 138 | - Because the project use a new audio library, the previous code is no longer applicable. 139 | - All the previous code is in the old-src folder, please refer to readme-oldversion. 140 | 141 | 142 | 143 | # Blue Tooth Stereo 144 | 145 | - Install "btAudio" lib from [tierneytim/btAudio](https://github.com/tierneytim/btAudio) 146 | 147 | - Upload "/Project_MakePython_Audio_Music/bluetooth_stereo/bluetooth_stereo.ino". 148 | - Opend your phone and select Bluetooth device "ESP_Speaker" 149 | - Use just like a usual Bluetooth Stereo. 150 | --------------------------------------------------------------------------------