Merge branch 'master' into patch-1

This commit is contained in:
tobozo 2023-10-17 16:27:25 +00:00 committed by GitHub
commit c46f3d3e12
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
50 changed files with 11832 additions and 231 deletions

View File

@ -13,6 +13,29 @@ on:
jobs:
build-rp2040:
name: Build RP2040
runs-on: ubuntu-latest
strategy:
matrix:
chunk: [0, 1, 2, 3, 4]
steps:
- uses: actions/checkout@v2
with:
submodules: true
- uses: actions/setup-python@v2
with:
python-version: '3.x'
- name: Build Sketches
env:
TRAVIS_BUILD_DIR: ${{ github.workspace }}
TRAVIS_TAG: ${{ github.ref }}
BUILD_TYPE: build_rp2040
BUILD_MOD: 5
BUILD_REM: ${{ matrix.chunk }}
run: |
bash ./tests/common.sh
build-esp8266:
name: Build ESP8266
runs-on: ubuntu-latest
@ -36,7 +59,6 @@ jobs:
run: |
bash ./tests/common.sh
build-esp32:
name: Build ESP-32
runs-on: ubuntu-latest
@ -84,7 +106,11 @@ jobs:
valgrind --leak-check=full --track-origins=yes -v --error-limit=no --show-leak-kinds=all --error-exitcode=999 ./mp3
valgrind --leak-check=full --track-origins=yes -v --error-limit=no --show-leak-kinds=all --error-exitcode=999 ./aac
valgrind --leak-check=full --track-origins=yes -v --error-limit=no --show-leak-kinds=all --error-exitcode=999 ./wav
valgrind --leak-check=full --track-origins=yes -v --error-limit=no --show-leak-kinds=all --error-exitcode=999 ./flac
valgrind --leak-check=full --track-origins=yes -v --error-limit=no --show-leak-kinds=all --error-exitcode=999 ./mod
valgrind --leak-check=full --track-origins=yes -v --error-limit=no --show-leak-kinds=all --error-exitcode=999 ./wav
valgrind --leak-check=full --track-origins=yes -v --error-limit=no --show-leak-kinds=all --error-exitcode=999 ./midi
valgrind --leak-check=full --track-origins=yes -v --error-limit=no --show-leak-kinds=all --error-exitcode=999 ./opus
lint:
runs-on: ubuntu-latest
@ -108,5 +134,5 @@ jobs:
- name: Run codespell
uses: codespell-project/actions-codespell@master
with:
skip: ./src/libmad,./src/libhelix-aac,./src/libopus
skip: ./src/libmad,./src/libhelix-aac,./src/libopus,./src/libflac
ignore_words_list: ESP8266,esp8266,esp,dout,DOUT,ser,ans,inout,numer,hist

View File

@ -1,4 +1,4 @@
# ESP8266Audio - supports ESP8266 & ESP32 & Raspberry Pi RP2040[![Gitter](https://badges.gitter.im/ESP8266Audio/community.svg)](https://gitter.im/ESP8266Audio/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
# ESP8266Audio - supports ESP8266 & ESP32 & Raspberry Pi Pico RP2040 [![Gitter](https://badges.gitter.im/ESP8266Audio/community.svg)](https://gitter.im/ESP8266Audio/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
Arduino library for parsing and decoding MOD, WAV, MP3, FLAC, MIDI, AAC, and RTTL files and playing them on an I2S DAC or even using a software-simulated delta-sigma DAC with dynamic 32x-128x oversampling.
ESP8266 is fully supported and most mature, but ESP32 is also mostly there with built-in DAC as well as external ones.
@ -6,34 +6,25 @@ ESP8266 is fully supported and most mature, but ESP32 is also mostly there with
For real-time, autonomous speech synthesis, check out [ESP8266SAM](https://github.com/earlephilhower/ESP8266SAM), a library which uses this one and a port of an ancient format-based synthesis program to allow your ESP8266 to talk with low memory and no network required.
## Disclaimer
All this code is released under the GPL, and all of it is to be used at your own risk. If you find any bugs, please let me know via the GitHub issue tracker or drop me an email. The MOD and MP3 routines were taken from StellaPlayer and libMAD respectively. The software I2S delta-sigma 32x oversampling DAC was my own creation, and sounds quite good if I do say so myself.
All this code is released under the GPL, and all of it is to be used at your own risk. If you find any bugs, please let me know via the GitHub issue tracker or drop me an email.
The AAC decode code is from the Helix project and licensed under RealNetwork's RSPL license. For commercial use you're still going to need the usual AAC licensing from [Via Licensing](http://www.via-corp.com/us/en/licensing/aac/overview.html).
On the ESP32, AAC-SBR is supported (many webradio stations use this to reduce bandwidth even further). The ESP8266, however, does not support it due to a lack of onboard RAM.
MIDI decoding comes from a highly ported [MIDITONES](https://github.com/LenShustek/miditones) combined with a massively memory-optimized [TinySoundFont](https://github.com/schellingb/TinySoundFont), see the respective source files for more information.
Opus, OGG, and OpusFile are from [Xiph.org](https://xiph.org) with the Xiph license and patent described in src/{opusfile,libggg,libopus}/COPYING.. **NOTE** Opus decoding currently only works on the ESP32 due to the large memory requirements of opusfile. PRs to rewrite it to be less memory intensive would be much appreciated.
* The MOD and MP3 routines were taken from StellarPlayer and libMAD respectively.
* The software I2S delta-sigma 32x oversampling DAC was my own creation, and sounds quite good if I do say so myself.
* The AAC decode code is from the Helix project and licensed under RealNetwork's RSPL license. For commercial use you're still going to need the usual AAC licensing from [Via Licensing](http://www.via-corp.com/us/en/licensing/aac/overview.html). On the ESP32, AAC-SBR is supported (many webradio stations use this to reduce bandwidth even further). The ESP8266, however, does not support it due to a lack of onboard RAM.
* MIDI decoding comes from a highly ported [MIDITONES](https://github.com/LenShustek/miditones) combined with a massively memory-optimized [TinySoundFont](https://github.com/schellingb/TinySoundFont), see the respective source files for more information.
* Opus, OGG, and OpusFile are from [Xiph.org](https://xiph.org) with the Xiph license and patent described in src/{opusfile,libggg,libopus}/COPYING.. **NOTE** Opus decoding currently only works on the ESP32 due to the large memory requirements of opusfile. PRs to rewrite it to be less memory intensive would be much appreciated.
## Neat Things People Have Done With ESP8266Audio
If you have a neat use for this library, [I'd love to hear about it](mailto:earlephilhower@yahoo.com)!
My personal use of the ESP8266Audio library is only to drive a 3D-printed, network-time-setting alarm clock for my kids which can play an MP3 instead of a bell to wake them up, called [Psychoclock](https://github.com/earlephilhower/psychoclock).
Harald Sattler has built a neat German [word clock with MP3 alarm](http://www.harald-sattler.de/html/mini-wecker.htm). Detailed discussion on the process and models are included.
Erich Heinemann has developed a Stomper (instrument for playing samples in real-time during a live stage performance) that you can find more info about [here](https://github.com/ErichHeinemann/hman-stomper).
Dagnall53 has integrated this into a really neat MQTT based model train controller to add sounds to his set. More info is available [here](https://github.com/dagnall53/ESPMQTTRocnetSound), including STL files for 3D printed components!
JohannesMTC has built a similar project especially for model trains: https://github.com/JohannesMTC/ESP32_MAS
A neat MQTT-driven ESP8266 light-and-sound device (alarm? toy? who can say!) was built by @CosmicMac, available at https://github.com/CosmicMac/ESParkle
A very interesting "linear clock" with a stepper motor, NTP time keeping, and configurable recorded chimes with schematics, 3D printer plans, and source code, is now available https://janderogee.com/projects/linear_clock/linear_clock.htm
Source and instructions for a gorgeous wooden MP3-playing clock, FM radio and a walkie-talkie using the ESP8266 and AVR microcontrollers is available https://github.com/zduka/mp3-player
* My personal use of the ESP8266Audio library is only to drive a 3D-printed, network-time-setting alarm clock for my kids which can play an MP3 instead of a bell to wake them up, called [Psychoclock](https://github.com/earlephilhower/psychoclock).
* Harald Sattler has built a neat German [word clock with MP3 alarm](http://www.harald-sattler.de/html/mini-wecker.htm). Detailed discussion on the process and models are included.
* Erich Heinemann has developed a Stomper (instrument for playing samples in real-time during a live stage performance) that you can find more info about [here](https://github.com/ErichHeinemann/hman-stomper).
* Dagnall53 has integrated this into a really neat MQTT based model train controller to add sounds to his set. More info is available [here](https://github.com/dagnall53/ESPMQTTRocnetSound), including STL files for 3D printed components!
* JohannesMTC has built a similar project especially for model trains: https://github.com/JohannesMTC/ESP32_MAS
* A neat MQTT-driven ESP8266 light-and-sound device (alarm? toy? who can say!) was built by @CosmicMac, available at https://github.com/CosmicMac/ESParkle
* A very interesting "linear clock" with a stepper motor, NTP time keeping, and configurable recorded chimes with schematics, 3D printer plans, and source code, is now available https://janderogee.com/projects/linear_clock/linear_clock.htm
* Source and instructions for a gorgeous wooden MP3-playing clock, FM radio and a walkie-talkie using the ESP8266 and AVR microcontrollers is available https://github.com/zduka/mp3-player
## Prerequisites
First, make sure you are running the 2.6.3/later or GIT head version of the Arduino libraries for ESP8266, or the latest ESP32 SDK from Espressif.
@ -181,7 +172,7 @@ I've used several versions of PCM5102 DAC boards purchased from eBay. They've a
### Others
There are many other variants out there, and they should all work reasonably well with this code and the ESP8266. Please be certain you've read the datasheet and are applying proper input voltages, and be sure to tie off any unused inputs to GND or VCC as appropriate. LEaving an input pin floating on any integrated circuit can cause unstable operation as it may pick up noise from the environment (very low input capacitance) and cause havoc with internal IC settings.
There are many other variants out there, and they should all work reasonably well with this code and the ESP8266. Please be certain you've read the datasheet and are applying proper input voltages, and be sure to tie off any unused inputs to GND or VCC as appropriate. Leaving an input pin floating on any integrated circuit can cause unstable operation as it may pick up noise from the environment (very low input capacitance) and cause havoc with internal IC settings.
## Software I2S Delta-Sigma DAC (i.e. playing music with a single transistor and speaker)
For the best fidelity, and stereo to boot, spend the money on a real I2S DAC. Adafruit makes a great mono one with amplifier, and you can find stereo unamplified ones on eBay or elsewhere quite cheaply. However, thanks to the software delta-sigma DAC with 32x oversampling (up to 128x if the audio rate is low enough) you can still have pretty good sound!
@ -216,7 +207,7 @@ USB-5V -- Speaker + Terminal
*NOTE*: A prior version of this schematic had a direct connection from the ESP8266 to the base of the transistor. While this does provide the maximum amplitude, it also can draw more current from the 8266 than is safe, and can also cause the transistor to overheat.
As of the latest ESP8266Audio release, with the software delta-sigma DAC the LRCLK and BCLK pins *can* be used by an application. Simply use normal `pinMode` and `dicitalWrite` or `digitalRead` as desired.
As of the latest ESP8266Audio release, with the software delta-sigma DAC the LRCLK and BCLK pins *can* be used by an application. Simply use normal `pinMode` and `digitalWrite` or `digitalRead` as desired.
### High pitched buzzing with the 1-T circuit
The 1-T amp can _NOT_ drive any sort of amplified speaker. If there is a power or USB input to the speaker, or it has lights or Bluetooth or a battery, it can _NOT_ be used with this circuit.
@ -249,7 +240,7 @@ ESP Pin -------|____|--------+
|
Ground ---------------------+
```
For ESP8266 with red LED (~1.9Vf drop) you need minimum 150Ohm resistor (12mA max per pin), and output pin is fixed (GPIO3/RX0).On ESP32 it is confgurable with `AudioOutputSPDIF(gpio_num)`.
For ESP8266 with red LED (~1.9Vf drop) you need minimum 150Ohm resistor (12mA max per pin), and output pin is fixed (GPIO3/RX0).On ESP32 it is configurable with `AudioOutputSPDIF(gpio_num)`.
## Using external SPI RAM to increase buffer
A class allows you to use a 23lc1024 SPI RAM from Microchip as input buffer. This chip connects to ESP8266 HSPI port and provides a large buffer to help avoid hiccus in playback of web streams.
@ -265,10 +256,11 @@ I've been told the Wemos SD card shield uses GPIO15 as the SD chip select. This
There's no ESP8266-specific code in the AudioGenerator routines, so porting to other controllers should be relatively easy assuming they have the same endianness as the Xtensa core used. Drop me a line if you're doing this, I may be able to help point you in the right direction.
## Thanks
Thanks to the authors of StellaPlayer and libMAD for releasing their code freely, and to the maintainers and contributors to the ESP8266 Arduino port.
Thanks to the authors of StellarPlayer and libMAD for releasing their code freely, and to the maintainers and contributors to the ESP8266 Arduino port.
Also, big thanks to @tueddy for getting the initial ESP32 porting into the tree!
-Earle F. Philhower, III
earlephilhower@yahoo.com

View File

@ -1,5 +1,10 @@
#include <Arduino.h>
#ifdef ESP32
#if defined(ARDUINO_ARCH_RP2040)
#define WIFI_OFF
class __x { public: __x() {}; void mode() {}; };
__x WiFi;
#elif defined(ESP32)
#include <WiFi.h>
#else
#include <ESP8266WiFi.h>

View File

@ -1,4 +1,8 @@
#include <Arduino.h>
#ifdef ARDUINO_ARCH_RP2040
void setup() {}
void loop() {}
#else
#include "AudioFileSourceSD.h"
#include "AudioOutputSPDIF.h"
#include "AudioGeneratorFLAC.h"
@ -66,3 +70,5 @@ void loop() {
}
}
}
#endif

View File

@ -6,7 +6,13 @@
}
void loop() {}
#else
#include <ESP8266WiFi.h>
#if defined(ARDUINO_ARCH_RP2040)
#define WIFI_OFF
class __x { public: __x() {}; void mode() {}; };
__x WiFi;
#else
#include <ESP8266WiFi.h>
#endif
#include <AudioOutputI2S.h>
#include <AudioGeneratorMIDI.h>
#include <AudioFileSourceLittleFS.h>
@ -42,7 +48,6 @@ void loop()
{
if (midi->isRunning()) {
if (!midi->loop()) {
uint32_t e = millis();
midi->stop();
}
} else {

View File

@ -1,4 +1,11 @@
#include <Arduino.h>
// Do not build on GCC8, GCC8 has a compiler bug
#if defined(ARDUINO_ARCH_RP2040) || ((__GNUC__ == 8) && (__XTENSA__))
void setup() {}
void loop() {}
#else
#ifdef ESP32
#include <WiFi.h>
#include "SPIFFS.h"
@ -44,7 +51,6 @@ void loop()
{
if (midi->isRunning()) {
if (!midi->loop()) {
uint32_t e = millis();
midi->stop();
}
} else {
@ -53,4 +59,4 @@ void loop()
}
}
#endif

View File

@ -2,7 +2,11 @@
#include "AudioFileSourcePROGMEM.h"
#include "AudioGeneratorMOD.h"
#include "AudioOutputI2S.h"
#ifdef ESP32
#if defined(ARDUINO_ARCH_RP2040)
#define WIFI_OFF
class __x { public: __x() {}; void mode() {}; };
__x WiFi;
#elif defined(ESP32)
#include <WiFi.h>
#else
#include <ESP8266WiFi.h>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,47 @@
#include <Arduino.h>
#include "AudioFileSourcePROGMEM.h"
#include "AudioGeneratorMOD.h"
#include "AudioOutputPWM.h"
#if !defined(ARDUINO_ARCH_RP2040)
void setup() {
Serial.begin(115200);
Serial.printf("Only for the RP2040/Raspberry Pi Pico\n");
}
void loop() {
}
#else
// 5_steps.mod sample from the mod archive: https://modarchive.org/
#include "5steps.h"
AudioGeneratorMOD *mod;
AudioFileSourcePROGMEM *file;
AudioOutputPWM *out;
void setup()
{
Serial.begin(115200);
delay(1000);
audioLogger = &Serial;
file = new AudioFileSourcePROGMEM(steps_mod, sizeof(steps_mod));
out = new AudioOutputPWM();
mod = new AudioGeneratorMOD();
mod->SetBufferSize(3*1024);
mod->SetSampleRate(44100);
mod->SetStereoSeparation(32);
mod->begin(file, out);
}
void loop()
{
if (mod->isRunning()) {
if (!mod->loop()) mod->stop();
} else {
Serial.printf("MOD done\n");
delay(1000);
}
}
#endif

View File

@ -1,4 +1,9 @@
#include <Arduino.h>
#if defined(ARDUINO_ARCH_RP2040)
void setup() {}
void loop() {}
#else
#ifdef ESP32
#include <WiFi.h>
#include "SPIFFS.h"
@ -70,3 +75,4 @@ void loop()
delay(1000);
}
}
#endif

View File

@ -1,4 +1,8 @@
#include <Arduino.h>
#ifdef ARDUINO_ARCH_RP2040
void setup() {}
void loop() {}
#else
#ifdef ESP32
#include "SPIFFS.h"
#endif
@ -97,3 +101,4 @@ void loop()
delay(1000);
}
}
#endif

View File

@ -1,4 +1,8 @@
#include <Arduino.h>
#ifdef ARDUINO_ARCH_RP2040
void setup() {}
void loop() {}
#else
#ifdef ESP32
#include <WiFi.h>
#include "SPIFFS.h"
@ -39,3 +43,5 @@ void loop()
delay(1000);
}
}
#endif

View File

@ -1,6 +1,11 @@
#include <Arduino.h>
#ifdef ESP32
#if defined(ARDUINO_ARCH_RP2040)
void setup() {}
void loop() {}
#else
#if defined(ESP32)
#include <WiFi.h>
#else
#include <ESP8266WiFi.h>
@ -104,4 +109,4 @@ void loop()
delay(1000);
}
}
#endif

View File

@ -1,6 +1,10 @@
#include <Arduino.h>
#ifdef ARDUINO_ARCH_RP2040
void setup() {}
void loop() {}
#else
#ifdef ESP32
#if defined(ESP32)
#include <WiFi.h>
#else
#include <ESP8266WiFi.h>
@ -140,3 +144,5 @@ void loop()
ESP.restart();
}
}
#endif

View File

@ -1,5 +1,9 @@
#include <Arduino.h>
#ifdef ESP32
#if defined(ARDUINO_ARCH_RP2040)
void setup() {}
void loop() {}
#else
#if defined(ESP32)
#include <WiFi.h>
#else
#include <ESP8266WiFi.h>
@ -101,4 +105,4 @@ void loop()
delay(1000);
}
}
#endif

View File

@ -29,7 +29,8 @@ class AudioOutputNullSlow : public AudioOutput
AudioOutputNullSlow() { };
~AudioOutputNullSlow() {};
virtual bool begin() { samples = 0; startms = millis(); return true; }
virtual bool ConsumeSample([[maybe_unused]] int16_t sample[2]) {
virtual bool ConsumeSample(int16_t sample[2]) {
(void) sample;
// return false (= output buffer full)
// sometimes to let the main loop running
constexpr int everylog2 = 10;

View File

@ -1,6 +1,10 @@
#include <Arduino.h>
#ifdef ESP32
#if defined(ARDUINO_ARCH_RP2040)
void setup() {}
void loop() {}
#else
#if defined(ESP32)
#include <WiFi.h>
#else
#include <ESP8266WiFi.h>
@ -9,10 +13,10 @@
#include "AudioFileSourceBuffer.h"
#include "AudioGeneratorMP3.h"
#if AUDIO
#pragma message("Outputting audio")
// #pragma message("Outputting audio")
#include "AudioOutputLinuxDSP.h"
#else
#pragma message("No audio")
// #pragma message("No audio")
#include "AudioOutputNullSlow.h"
#endif
@ -115,4 +119,4 @@ void loop()
delay(1000);
}
}
#endif

View File

@ -2,7 +2,14 @@
// https://github.com/going-digital/Talkie/blob/master/Talkie/examples/Vocab_US_Clock/Vocab_US_Clock.ino
// Released under GPL v2
#ifdef ESP32
#include <Arduino.h>
#if defined(ARDUINO_ARCH_RP2040)
void setup() {}
void loop() {}
#else
#if defined(ESP32)
#include <WiFi.h>
#else
#include <ESP8266WiFi.h>
@ -183,3 +190,4 @@ void loop()
sayTime(tmstruct.tm_hour, tmstruct.tm_min, talkie);
delay(1000);
}
#endif

View File

@ -19,7 +19,15 @@
*/
#include <Arduino.h>
#ifdef ESP32
#if defined(ARDUINO_ARCH_RP2040)
void setup() {}
void loop() {}
#else
// ESP8266 server.available() is now server.accept()
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#if defined(ESP32)
#include <WiFi.h>
#else
#include <ESP8266WiFi.h>
@ -439,3 +447,4 @@ void loop()
}
}
#endif

View File

@ -19,6 +19,9 @@
*/
#include <Arduino.h>
#if defined(ARDUINO_ARCH_RP2040)
// Nothing here
#else
#ifdef ESP32
#include <WiFi.h>
#else
@ -308,7 +311,4 @@ void Read4Int(char *str, byte *p)
str += ParseInt(str, &i); p[2] = i; if (*str) str++;
str += ParseInt(str, &i); p[3] = i;
}
#endif

View File

@ -23,6 +23,7 @@ AudioOutput KEYWORD1
AudioOutputI2S KEYWORD1
AudioOutputI2SNoDAC KEYWORD1
AudioOutputI2SClass KEYWORD1
AudioOutputPWM KEYWORD1
AudioOutputNull KEYWORD1
AudioOutputBuffer KEYWORD1
AudioOutputSerialWAV KEYWORD1

View File

@ -14,7 +14,7 @@
"type": "git",
"url": "https://github.com/earlephilhower/ESP8266Audio"
},
"version": "1.9.6",
"version": "1.9.7",
"homepage": "https://github.com/earlephilhower/ESP8266Audio",
"frameworks": "Arduino",
"examples": [

View File

@ -1,5 +1,5 @@
name=ESP8266Audio
version=1.9.6
version=1.9.7
author=Earle F. Philhower, III
maintainer=Earle F. Philhower, III
sentence=Audio file and I2S sound playing routines for ESP8266, ESP32, and Raspberry Pi Pico RP2040

View File

@ -25,14 +25,14 @@ AudioFileSourceFunction::AudioFileSourceFunction(float sec, uint16_t channels, u
uint32_t len = uint32_t(sec * (float)bytes_per_sec);
// RIFF chunk
strncpy(wav_header.riff.chunk_id, "RIFF", 4);
memcpy(wav_header.riff.chunk_id, "RIFF", 4);
wav_header.riff.chunk_size = 4 // size of riff chunk w/o chunk_id and chunk_size
+ 8 + 16 // size of format chunk
+ 8 + len; // size of data chunk
strncpy(wav_header.riff.format, "WAVE", 4);
memcpy(wav_header.riff.format, "WAVE", 4);
// format chunk
strncpy(wav_header.format.chunk_id, "fmt ", 4);
memcpy(wav_header.format.chunk_id, "fmt ", 4);
wav_header.format.chunk_size = 16;
wav_header.format.format_tag = 0x0001; // PCM
wav_header.format.channels = channels;
@ -42,7 +42,7 @@ AudioFileSourceFunction::AudioFileSourceFunction(float sec, uint16_t channels, u
wav_header.format.bits_per_sample = bits_per_sample;
// data chunk
strncpy(wav_header.data.chunk_id, "data", 4);
memcpy(wav_header.data.chunk_id, "data", 4);
wav_header.data.chunk_size = len;
funcs.reserve(channels);

View File

@ -20,6 +20,9 @@
#if defined(ESP32) || defined(ESP8266)
#ifdef _GNU_SOURCE
#undef _GNU_SOURCE
#endif
#define _GNU_SOURCE
#include "AudioFileSourceICYStream.h"

View File

@ -27,6 +27,9 @@
#include "AudioFileSource.h"
#include "AudioFileSourceFS.h"
// Yes, I know SPIFFS is deprecated
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
class AudioFileSourceSPIFFS : public AudioFileSourceFS
{
public:

View File

@ -62,6 +62,9 @@ bool AudioGeneratorFLAC::begin(AudioFileSource *source, AudioOutput *output)
output->begin();
running = true;
lastSample[0] = 0;
lastSample[1] = 0;
channels = 0;
return true;
}
@ -71,7 +74,7 @@ bool AudioGeneratorFLAC::loop()
if (!running) goto done;
if (!output->ConsumeSample(lastSample)) goto done; // Try and send last buffered sample
if (channels && !output->ConsumeSample(lastSample)) goto done; // Try and send last buffered sample
do {
if (buffPtr == buffLen) {

View File

@ -58,7 +58,7 @@
#include "AudioGeneratorMIDI.h"
#if __GNUC__ == 8
#if (__GNUC__ == 8) && (__XTENSA__)
// Do not build, GCC8 has a compiler bug
#else // __GNUC__ == 8

View File

@ -21,7 +21,7 @@
#ifndef _AUDIOGENERATORMIDI_H
#define _AUDIOGENERATORMIDI_H
#if __GNUC__ == 8
#if (__GNUC__ == 8) && (__XTENSA__)
// Do not build, GCC8 has a compiler bug
#else // __GNUC__ == 8

View File

@ -791,7 +791,7 @@ void AudioGeneratorMOD::GetSample(int16_t sample[2])
Mixer.channelSampleNumber[channel] != FatBuffer.channelSampleNumber[channel]) {
uint32_t toRead = Mixer.sampleEnd[Mixer.channelSampleNumber[channel]] - samplePointer + 1;
if (toRead > fatBufferSize) toRead = fatBufferSize;
if (toRead > (uint32_t)fatBufferSize) toRead = fatBufferSize;
if (!file->seek(samplePointer, SEEK_SET)) {
stop();

View File

@ -248,6 +248,10 @@ retry:
running = false;
goto done;
}
if (lastChannels == 1)
{
lastSample[1] = lastSample[0];
}
} while (running && output->ConsumeSample(lastSample));
done:

View File

@ -127,7 +127,7 @@ bool AudioGeneratorWAV::ReadWAVInfo()
return false;
};
if (u32 != 0x46464952) {
Serial.printf_P(PSTR("AudioGeneratorWAV::ReadWAVInfo: cannot read WAV, invalid RIFF header, got: %08X \n"), (uint32_t) u32);
Serial.printf_P(PSTR("AudioGeneratorWAV::ReadWAVInfo: cannot read WAV, invalid RIFF header\n"));
return false;
}
@ -143,7 +143,7 @@ bool AudioGeneratorWAV::ReadWAVInfo()
return false;
};
if (u32 != 0x45564157) {
Serial.printf_P(PSTR("AudioGeneratorWAV::ReadWAVInfo: cannot read WAV, invalid WAVE header, got: %08X \n"), (uint32_t) u32);
Serial.printf_P(PSTR("AudioGeneratorWAV::ReadWAVInfo: cannot read WAV, invalid WAVE header\n"));
return false;
}

View File

@ -85,9 +85,31 @@ AudioOutputI2S::AudioOutputI2S(int port, int output_mode, int dma_buf_count, int
bclkPin = 26;
wclkPin = 25;
doutPin = 22;
mclkPin = 0;
SetGain(1.0);
}
#elif defined(ARDUINO_ARCH_RP2040)
AudioOutputI2S::AudioOutputI2S(long sampleRate, pin_size_t sck, pin_size_t data) {
i2sOn = false;
mono = false;
bps = 16;
channels = 2;
hertz = sampleRate;
bclkPin = sck;
doutPin = data;
mclkPin = 0;
use_mclk = false;
swap_clocks = false;
SetGain(1.0);
}
#endif
AudioOutputI2S::~AudioOutputI2S()
{
stop();
}
bool AudioOutputI2S::SetPinout()
{
#ifdef ESP32
@ -95,6 +117,9 @@ bool AudioOutputI2S::SetPinout()
return false; // Not allowed
i2s_pin_config_t pins = {
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0)
.mck_io_num = mclkPin,
#endif
.bck_io_num = bclkPin,
.ws_io_num = wclkPin,
.data_out_num = doutPin,
@ -105,6 +130,8 @@ bool AudioOutputI2S::SetPinout()
(void)bclkPin;
(void)wclkPin;
(void)doutPin;
(void)mclkPin;
(void)use_mclk;
return false;
#endif
}
@ -119,33 +146,20 @@ bool AudioOutputI2S::SetPinout(int bclk, int wclk, int dout)
return true;
}
#elif defined(ARDUINO_ARCH_RP2040)
AudioOutputI2S::AudioOutputI2S(long sampleRate, pin_size_t sck, pin_size_t data) {
i2sOn = false;
mono = false;
bps = 16;
channels = 2;
hertz = sampleRate;
bclkPin = sck;
doutPin = data;
SetGain(1.0);
}
#endif
AudioOutputI2S::~AudioOutputI2S()
bool AudioOutputI2S::SetPinout(int bclk, int wclk, int dout, int mclk)
{
bclkPin = bclk;
wclkPin = wclk;
doutPin = dout;
#ifdef ESP32
if (i2sOn) {
audioLogger->printf("UNINSTALL I2S\n");
i2s_driver_uninstall((i2s_port_t)portNo); //stop & destroy i2s driver
}
#elif defined(ESP8266)
mclkPin = mclk;
if (i2sOn)
i2s_end();
#elif defined(ARDUINO_ARCH_RP2040)
stop();
return SetPinout();
#else
(void)mclk;
#endif
i2sOn = false;
return true;
}
bool AudioOutputI2S::SetRate(int hz)
@ -159,7 +173,7 @@ bool AudioOutputI2S::SetRate(int hz)
#elif defined(ESP8266)
i2s_set_rate(AdjustI2SRate(hz));
#elif defined(ARDUINO_ARCH_RP2040)
I2S.setFrequency(hz);
i2s.setFrequency(hz);
#endif
}
return true;
@ -191,6 +205,26 @@ bool AudioOutputI2S::SetLsbJustified(bool lsbJustified)
return true;
}
bool AudioOutputI2S::SwapClocks(bool swap_clocks)
{
if (i2sOn) {
return false; // Not allowed
}
this->swap_clocks = swap_clocks;
return true;
}
bool AudioOutputI2S::SetMclk(bool enabled){
(void)enabled;
#ifdef ESP32
if (output_mode == INTERNAL_DAC || output_mode == INTERNAL_PDM)
return false; // Not allowed
use_mclk = enabled;
#endif
return true;
}
bool AudioOutputI2S::begin(bool txDAC)
{
#ifdef ESP32
@ -249,7 +283,13 @@ bool AudioOutputI2S::begin(bool txDAC)
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, // lowest interrupt priority
.dma_buf_count = dma_buf_count,
.dma_buf_len = 128,
.use_apll = use_apll // Use audio PLL
.use_apll = use_apll, // Use audio PLL
.tx_desc_auto_clear = true, // Silence on underflow
.fixed_mclk = use_mclk, // Unused
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0)
.mclk_multiple = I2S_MCLK_MULTIPLE_256, // Unused
.bits_per_chan = I2S_BITS_PER_CHAN_DEFAULT // Use bits per sample
#endif
};
audioLogger->printf("+%d %p\n", portNo, &i2s_config_dac);
if (i2s_driver_install((i2s_port_t)portNo, &i2s_config_dac, 0, NULL) != ESP_OK)
@ -294,9 +334,12 @@ bool AudioOutputI2S::begin(bool txDAC)
#elif defined(ARDUINO_ARCH_RP2040)
(void)txDAC;
if (!i2sOn) {
I2S.setBCLK(bclkPin);
I2S.setDOUT(doutPin);
I2S.begin(hertz);
i2s.setBCLK(bclkPin);
i2s.setDATA(doutPin);
if (swap_clocks) {
i2s.swapClocks();
}
i2s.begin(hertz);
}
#endif
i2sOn = true;
@ -344,7 +387,8 @@ bool AudioOutputI2S::ConsumeSample(int16_t sample[2])
uint32_t s32 = ((Amplify(ms[RIGHTCHANNEL])) << 16) | (Amplify(ms[LEFTCHANNEL]) & 0xffff);
return i2s_write_sample_nb(s32); // If we can't store it, return false. OTW true
#elif defined(ARDUINO_ARCH_RP2040)
return !!I2S.write((void*)ms, 4);
uint32_t s32 = ((Amplify(ms[RIGHTCHANNEL])) << 16) | (Amplify(ms[LEFTCHANNEL]) & 0xffff);
return !!i2s.write((int32_t)s32, false);
#endif
}
@ -362,7 +406,7 @@ void AudioOutputI2S::flush()
}
}
#elif defined(ARDUINO_ARCH_RP2040)
I2S.flush();
i2s.flush();
#endif
}
@ -373,8 +417,12 @@ bool AudioOutputI2S::stop()
#ifdef ESP32
i2s_zero_dma_buffer((i2s_port_t)portNo);
audioLogger->printf("UNINSTALL I2S\n");
i2s_driver_uninstall((i2s_port_t)portNo); //stop & destroy i2s driver
#elif defined(ESP8266)
i2s_end();
#elif defined(ARDUINO_ARCH_RP2040)
I2S.end();
i2s.end();
#endif
i2sOn = false;
return true;

View File

@ -22,17 +22,23 @@
#include "AudioOutput.h"
#if defined(ARDUINO_ARCH_RP2040)
#include <Arduino.h>
#include <I2S.h>
#endif
class AudioOutputI2S : public AudioOutput
{
public:
#if defined(ESP32) || defined(ESP8266)
AudioOutputI2S(int port=0, int output_mode=EXTERNAL_I2S, int dma_buf_count = 8, int use_apll=APLL_DISABLE);
bool SetPinout(int bclkPin, int wclkPin, int doutPin);
enum : int { APLL_AUTO = -1, APLL_ENABLE = 1, APLL_DISABLE = 0 };
enum : int { EXTERNAL_I2S = 0, INTERNAL_DAC = 1, INTERNAL_PDM = 2 };
#elif defined(ARDUINO_ARCH_RP2040)
AudioOutputI2S(long sampleRate = 44100, pin_size_t sck = 26, pin_size_t data = 28);
#endif
bool SetPinout(int bclkPin, int wclkPin, int doutPin);
bool SetPinout(int bclkPin, int wclkPin, int doutPin, int mclkPin);
virtual ~AudioOutputI2S() override;
virtual bool SetRate(int hz) override;
virtual bool SetBitsPerSample(int bits) override;
@ -45,6 +51,8 @@ class AudioOutputI2S : public AudioOutput
bool begin(bool txDAC);
bool SetOutputModeMono(bool mono); // Force mono output no matter the input
bool SetLsbJustified(bool lsbJustified); // Allow supporting non-I2S chips, e.g. PT8211
bool SetMclk(bool enabled); // Enable MCLK output (if supported)
bool SwapClocks(bool swap_clocks); // Swap BCLK and WCLK
protected:
bool SetPinout();
@ -56,6 +64,8 @@ class AudioOutputI2S : public AudioOutput
bool i2sOn;
int dma_buf_count;
int use_apll;
bool use_mclk;
bool swap_clocks;
// We can restore the old values and free up these pins when in NoDAC mode
uint32_t orig_bck;
uint32_t orig_ws;
@ -63,4 +73,9 @@ class AudioOutputI2S : public AudioOutput
uint8_t bclkPin;
uint8_t wclkPin;
uint8_t doutPin;
uint8_t mclkPin;
#if defined(ARDUINO_ARCH_RP2040)
I2S i2s;
#endif
};

View File

@ -119,9 +119,6 @@ bool AudioOutputI2SNoDAC::ConsumeSample(int16_t sample[2])
// Either send complete pulse stream or nothing
#ifdef ESP32
//"i2s_write_bytes" has been removed in the ESP32 Arduino 2.0.0, use "i2s_write" instead.
// if (!i2s_write_bytes((i2s_port_t)portNo, (const char *)dsBuff, sizeof(uint32_t) * (oversample/32), 0))
size_t i2s_bytes_written;
i2s_write((i2s_port_t)portNo, (const char *)dsBuff, sizeof(uint32_t) * (oversample/32), &i2s_bytes_written, 0);
if (!i2s_bytes_written){
@ -134,9 +131,8 @@ bool AudioOutputI2SNoDAC::ConsumeSample(int16_t sample[2])
for (int i = 32; i < oversample; i+=32)
i2s_write_sample( dsBuff[i / 32]);
#elif defined(ARDUINO_ARCH_RP2040)
int16_t *p = (int16_t *) dsBuff;
for (int i = 0; i < oversample / 16; i++) {
I2S.write(*(p++));
for (int i = 0; i < oversample / 32; i++) {
i2s.write((int32_t)dsBuff[i], true);
}
#endif
return true;

View File

@ -43,7 +43,7 @@ class AudioOutputI2SNoDAC : public AudioOutputI2S
protected:
virtual int AdjustI2SRate(int hz) override { return hz * oversample/32; }
uint8_t oversample;
int oversample;
void DeltaSigma(int16_t sample[2], uint32_t dsBuff[4]);
typedef int32_t fixed24p8_t;
enum {fixedPosValue=0x007fff00}; /* 24.8 of max-signed-int */

114
src/AudioOutputPWM.cpp Normal file
View File

@ -0,0 +1,114 @@
/*
AudioOutputPWM
Base class for the RP2040 PWM audio
Copyright (C) 2023 Earle F. Philhower, III
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if defined(ARDUINO_ARCH_RP2040)
#include <Arduino.h>
#include "AudioOutputPWM.h"
AudioOutputPWM::AudioOutputPWM(long sampleRate, pin_size_t data) {
pwmOn = false;
mono = false;
bps = 16;
channels = 2;
hertz = sampleRate;
doutPin = data;
SetGain(1.0);
pwm.setStereo(true);
}
AudioOutputPWM::~AudioOutputPWM() {
stop();
}
bool AudioOutputPWM::SetRate(int hz) {
this->hertz = hz;
if (pwmOn) {
pwm.setFrequency(hz);
}
return true;
}
bool AudioOutputPWM::SetBitsPerSample(int bits) {
if ( (bits != 16) && (bits != 8) ) return false;
this->bps = bits;
return true;
}
bool AudioOutputPWM::SetChannels(int channels) {
if ( (channels < 1) || (channels > 2) ) return false;
this->channels = channels;
return true;
}
bool AudioOutputPWM::SetOutputModeMono(bool mono) {
this->mono = mono;
return true;
}
bool AudioOutputPWM::begin() {
if (!pwmOn) {
pwm.setPin(doutPin);
pwm.begin(hertz);
}
pwmOn = true;
SetRate(hertz); // Default
return true;
}
bool AudioOutputPWM::ConsumeSample(int16_t sample[2]) {
if (!pwmOn)
return false;
int16_t ms[2];
ms[0] = sample[0];
ms[1] = sample[1];
MakeSampleStereo16( ms );
if (this->mono) {
// Average the two samples and overwrite
int32_t ttl = ms[LEFTCHANNEL] + ms[RIGHTCHANNEL];
ms[LEFTCHANNEL] = ms[RIGHTCHANNEL] = (ttl>>1) & 0xffff;
}
if (pwm.available()) {
pwm.write((int16_t) ms[0]);
pwm.write((int16_t) ms[1]);
return true;
} else {
return false;
}
}
void AudioOutputPWM::flush() {
pwm.flush();
}
bool AudioOutputPWM::stop() {
if (!pwmOn)
return false;
pwm.end();
pwmOn = false;
return true;
}
#endif

57
src/AudioOutputPWM.h Normal file
View File

@ -0,0 +1,57 @@
/*
AudioOutputPWM
Base class for the RP2040 PWM audio output
Copyright (C) 2023 Earle F. Philhower, III
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "AudioOutput.h"
#if defined(ARDUINO_ARCH_RP2040)
#include <Arduino.h>
#include <PWMAudio.h>
class AudioOutputPWM : public AudioOutput
{
public:
AudioOutputPWM(long sampleRate = 44100, pin_size_t data = 0);
virtual ~AudioOutputPWM() override;
virtual bool SetRate(int hz) override;
virtual bool SetBitsPerSample(int bits) override;
virtual bool SetChannels(int channels) override;
virtual bool begin() override;
virtual bool ConsumeSample(int16_t sample[2]) override;
virtual void flush() override;
virtual bool stop() override;
bool SetOutputModeMono(bool mono); // Force mono output no matter the input
protected:
bool SetPinout();
virtual int AdjustI2SRate(int hz) { return hz; }
uint8_t portNo;
int output_mode;
bool mono;
bool pwmOn;
uint8_t doutPin;
PWMAudio pwm;
};
#endif

View File

@ -102,7 +102,13 @@ AudioOutputSPDIF::AudioOutputSPDIF(int dout_pin, int port, int dma_buf_count)
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, // lowest interrupt priority
.dma_buf_count = dma_buf_count,
.dma_buf_len = DMA_BUF_SIZE_DEFAULT, // bigger buffers, reduces interrupts
.use_apll = true // Audio PLL is needed for low clock jitter
.use_apll = true, // Audio PLL is needed for low clock jitter
.tx_desc_auto_clear = true, // Silence on underflow
.fixed_mclk = 0, // Unused
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0)
.mclk_multiple = I2S_MCLK_MULTIPLE_DEFAULT, // Unused
.bits_per_chan = I2S_BITS_PER_CHAN_DEFAULT // Use bits per sample
#endif
};
if (i2s_driver_install((i2s_port_t)portNo, &i2s_config_spdif, 0, NULL) != ESP_OK) {
audioLogger->println(F("ERROR: Unable to install I2S drivers"));
@ -147,6 +153,9 @@ bool AudioOutputSPDIF::SetPinout(int bclk, int wclk, int dout)
{
#if defined(ESP32)
i2s_pin_config_t pins = {
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0)
.mck_io_num = 0, // unused
#endif
.bck_io_num = bclk,
.ws_io_num = wclk,
.data_out_num = dout,

View File

@ -18,12 +18,18 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(ARDUINO_ARCH_RP2040)
#include <Arduino.h>
#include <FS.h>
#ifdef ESP32
#include "SPIFFS.h"
#endif
// Yes, I know SPIFFS is deprecated
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#include "AudioOutputSPIFFSWAV.h"
static const uint8_t wavHeaderTemplate[] PROGMEM = { // Hardcoded simple WAV header with 0xffffffff lengths all around
@ -110,4 +116,6 @@ bool AudioOutputSPIFFSWAV::stop()
f.close();
return true;
}
#endif

View File

@ -21,6 +21,8 @@
#ifndef _AUDIOOUTPUTSPIFFSWAV_H
#define _AUDIOOUTPUTSPIFFSWAV_H
#if !defined(ARDUINO_ARCH_RP2040)
#include <Arduino.h>
#include <FS.h>
@ -43,3 +45,4 @@ class AudioOutputSPIFFSWAV : public AudioOutput
#endif
#endif

View File

@ -41,6 +41,7 @@
#include "AudioOutput.h"
#include "AudioOutputI2S.h"
#include "AudioOutputI2SNoDAC.h"
#include "AudioOutputPWM.h"
#include "AudioOutputMixer.h"
#include "AudioOutputNull.h"
#include "AudioOutputSerialWAV.h"

View File

@ -35,7 +35,7 @@
* print an error message if it fails (ie returns a value < 0).
*
* Ideally, a library should not print anything, but this macro is only used
* for things that extremely unlikely to fail, like `chown` to a previoulsy
* for things that extremely unlikely to fail, like `chown` to a previously
* saved `uid`.
*/

View File

@ -2783,7 +2783,7 @@ FLAC__bool read_residual_partitioned_rice_(FLAC__StreamDecoder *decoder, uint32_
if(rice_parameter < pesc) {
partitioned_rice_contents->raw_bits[partition] = 0;
u = (partition_order == 0 || partition > 0)? partition_samples : partition_samples - predictor_order;
if(!FLAC__bitreader_read_rice_signed_block(decoder->private_->input, residual + sample, u, rice_parameter))
if(!FLAC__bitreader_read_rice_signed_block(decoder->private_->input, (int *)(residual + sample), u, rice_parameter))
return false; /* read_callback_ sets the state for us */
sample += u;
}
@ -2792,7 +2792,7 @@ FLAC__bool read_residual_partitioned_rice_(FLAC__StreamDecoder *decoder, uint32_
return false; /* read_callback_ sets the state for us */
partitioned_rice_contents->raw_bits[partition] = rice_parameter;
for(u = (partition_order == 0 || partition > 0)? 0 : predictor_order; u < partition_samples; u++, sample++) {
if(!FLAC__bitreader_read_raw_int32(decoder->private_->input, &i, rice_parameter))
if(!FLAC__bitreader_read_raw_int32(decoder->private_->input, (FLAC__int32 *)&i, rice_parameter))
return false; /* read_callback_ sets the state for us */
residual[sample] = i;
}

View File

@ -222,7 +222,8 @@ static void PostMultiply64(int *fft1, int nSampsOut)
* Notes: this is carefully written to be efficient on ARM
* use the assembly code version in sbrqmfak.s when building for ARM!
**************************************************************************************/
#if (defined (__arm) && defined (__ARMCC_VERSION)) || (defined (_WIN32) && defined (_WIN32_WCE) && defined (ARM)) || (defined(__GNUC__) && defined(__arm__))
//TODO - ADD IN .S SOURCES SOMEHOW
#if 0 //(defined (__arm) && defined (__ARMCC_VERSION)) || (defined (_WIN32) && defined (_WIN32_WCE) && defined (ARM)) || (defined(__GNUC__) && defined(__arm__))
#ifdef __cplusplus
extern "C"
#endif
@ -395,7 +396,7 @@ int QMFAnalysis(int *inbuf, int *delay, int *XBuf, int fBitsIn, int *delayIdx, i
* Notes: this is carefully written to be efficient on ARM
* use the assembly code version in sbrqmfsk.s when building for ARM!
**************************************************************************************/
#if (defined (__arm) && defined (__ARMCC_VERSION)) || (defined (_WIN32) && defined (_WIN32_WCE) && defined (ARM)) || (defined(__GNUC__) && defined(__arm__))
#if 0 //(defined (__arm) && defined (__ARMCC_VERSION)) || (defined (_WIN32) && defined (_WIN32_WCE) && defined (ARM)) || (defined(__GNUC__) && defined(__arm__))
#ifdef __cplusplus
extern "C"
#endif

View File

@ -20,6 +20,7 @@
*/
#pragma GCC optimize ("O3")
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
#include <pgmspace.h>
# include "config.h"

View File

@ -1440,6 +1440,7 @@ static void tsf_voice_render_fast(tsf* f, struct tsf_voice* v, short* outputBuff
//double tmpSampleEndDbl = (double)v->sampleEnd, tmpLoopEndDbl = (double)tmpLoopEnd + 1.0;
//double tmpSourceSamplePosition = v->sourceSamplePosition;
fixed32p32 tmpSampleEndF32P32 = ((fixed32p32)(region->end)) << 32;
fixed32p32 tmpLoopStartF32P32 = ((fixed32p32)(tmpLoopStart + 1)) << 32;
fixed32p32 tmpLoopEndF32P32 = ((fixed32p32)(tmpLoopEnd + 1)) << 32;
fixed32p32 tmpSourceSamplePositionF32P32 = v->sourceSamplePositionF32P32;
struct tsf_voice_lowpass tmpLowpass = v->lowpass;
@ -1513,7 +1514,7 @@ static void tsf_voice_render_fast(tsf* f, struct tsf_voice* v, short* outputBuff
// Next sample.
tmpSourceSamplePositionF32P32 += pitchRatioF32P32;
if (tmpSourceSamplePositionF32P32 >= tmpLoopEndF32P32 && isLooping)
tmpSourceSamplePositionF32P32 -= (tmpLoopEndF32P32 - tmpLoopStart + (1LL<<32));
tmpSourceSamplePositionF32P32 -= (tmpLoopEndF32P32 - tmpLoopStartF32P32 + (1LL<<32));
}
if (tmpSourceSamplePositionF32P32 >= tmpSampleEndF32P32 || v->ampenv.segment == TSF_SEGMENT_DONE)

View File

@ -1422,7 +1422,7 @@ static int op_open_seekable2_impl(OggOpusFile *_of){
_of->end=sr[0].offset+sr[0].size;
if(OP_UNLIKELY(_of->end<data_offset)){free(sr); return OP_EBADLINK;}
/*Now enumerate the bitstream structure.*/
ret = op_bisect_forward_serialno(_of,data_offset,sr,sizeof(sr)/sizeof(*sr),
ret = op_bisect_forward_serialno(_of,data_offset,sr,64,
&_of->serialnos,&_of->nserialnos,&_of->cserialnos);
free(sr);
return ret;

View File

@ -337,9 +337,9 @@ class ESP8266SPIRAM {
}
digitalWrite(csPin, HIGH);
pinMode(sck, SPECIAL);
pinMode(miso, SPECIAL);
pinMode(mosi, SPECIAL);
pinMode(sck, OUTPUT);
pinMode(miso, INPUT);
pinMode(mosi, OUTPUT);
pinMode(csPin, OUTPUT);
// Enable streaming read/write mode

View File

@ -2,98 +2,17 @@
set -ex
function print_size_info()
{
elf_file=$1
if [ -z "$elf_file" ]; then
printf "sketch data rodata bss text irom0.text dram flash\n"
return 0
fi
elf_name=$(basename $elf_file)
sketch_name="${elf_name%.*}"
# echo $sketch_name
declare -A segments
while read -a tokens; do
seg=${tokens[0]}
seg=${seg//./}
size=${tokens[1]}
addr=${tokens[2]}
if [ "$addr" -eq "$addr" -a "$addr" -ne "0" ] 2>/dev/null; then
segments[$seg]=$size
fi
done < <(xtensa-lx106-elf-size --format=sysv $elf_file)
total_ram=$((${segments[data]} + ${segments[rodata]} + ${segments[bss]}))
total_flash=$((${segments[data]} + ${segments[rodata]} + ${segments[text]} + ${segments[irom0text]}))
printf "%-28s %-8d %-8d %-8d %-8d %-8d %-8d %-8d\n" $sketch_name ${segments[data]} ${segments[rodata]} ${segments[bss]} ${segments[text]} ${segments[irom0text]} $total_ram $total_flash
return 0
}
function build_sketches()
{
set +e
local arduino=$1
local srcpath=$2
local build_arg=$3
local build_dir=build.tmp
local build_mod=$BUILD_MOD
local build_rem=$BUILD_REM
mkdir -p $build_dir
local build_cmd="python3 $arduino/$BUILD_PY -p $PWD/$build_dir $build_arg "
local sketches=$(find $srcpath -name *.ino)
print_size_info >size.log
export ARDUINO_IDE_PATH=$arduino
for sketch in $sketches; do
testcnt=$(( ($testcnt + 1) % $build_mod ))
if [ $testcnt -ne $build_rem ]; then
continue # Not ours to do
fi
rm -rf $build_dir/*
local sketchdir=$(dirname $sketch)
local sketchdirname=$(basename $sketchdir)
local sketchname=$(basename $sketch)
if [[ "${sketchdirname}.ino" != "$sketchname" ]]; then
echo "Skipping $sketch, because it is not the main sketch file";
continue
fi;
if [[ -f "$sketchdir/.test.skip" ]]; then
echo -e "\n ------------ Skipping $sketch ------------ \n";
continue
fi
echo -e "\n ------------ Building $sketch ------------ \n";
# $arduino --verify $sketch;
echo "$build_cmd $sketch"
time ($build_cmd $sketch >build.log)
local result=$?
if [ $result -ne 0 ]; then
echo "Build failed ($1)"
echo "Build log:"
cat build.log
set -e
return $result
fi
rm build.log
#print_size_info $build_dir/*.elf >>size.log
done
set -e
}
function install_libraries()
{
mkdir -p $HOME/Arduino/libraries
cp -a $TRAVIS_BUILD_DIR $HOME/Arduino/libraries/ESP8266Audio
cp -a $GITHUB_WORKSPACE $HOME/Arduino/libraries/ESP8266Audio
git clone https://github.com/earlephilhower/ESP8266SAM $HOME/Arduino/libraries/ESP8266SAM
}
function install_ide()
{
local ide_path=$1
wget -q -O arduino.tar.xz https://www.arduino.cc/download.php?f=/arduino-nightly-linux64.tar.xz
wget -q -O arduino.tar.xz https://downloads.arduino.cc/arduino-nightly-linux64.tar.xz
tar xf arduino.tar.xz
mv arduino-nightly $ide_path
export PATH="$ide_path:$PATH"
@ -111,84 +30,100 @@ function install_esp8266()
# Set custom warnings for all builds (i.e. could add -Wextra at some point)
echo "compiler.c.extra_flags=-Wall -Wextra -Werror $debug_flags" > ../platform.local.txt
echo "compiler.cpp.extra_flags=-Wall -Wextra -Werror $debug_flags" >> ../platform.local.txt
echo "mkbuildoptglobals.extra_flags=--ci --cache_core" >> ../platform.local.txt
echo -e "\n----platform.local.txt----"
cat ../platform.local.txt
git submodule init
git submodule update
python3 get.py
python3 get.py -q
export PATH="$ide_path/hardware/esp8266com/esp8266/tools/xtensa-lx106-elf/bin:$PATH"
popd
cd esp8266
}
function install_rp2040()
{
local ide_path=$1
mkdir -p $ide_path/hardware
cd $ide_path/hardware
mkdir pico
cd pico
git clone https://github.com/earlephilhower/arduino-pico rp2040
pushd rp2040/tools
# Set custom warnings for all builds (i.e. could add -Wextra at some point)
echo "compiler.c.extra_flags=-Wall -Wextra -Werror $debug_flags" > ../platform.local.txt
echo "compiler.cpp.extra_flags=-Wall -Wextra -Werror $debug_flags" >> ../platform.local.txt
echo -e "\n----platform.local.txt----"
cat ../platform.local.txt
git submodule update --init
cd ../pico-sdk
git submodule update --init
cd ../tools
python3 get.py -q
export PATH="$ide_path/hardware/pico/rp2040/system/arm-none-eabi/bin:$PATH"
popd
cd rp2040
}
function install_esp32()
{
local ide_path=$1
sudo pip install pyserial
pip install pyserial
pip3 install pyserial
cd $ide_path/hardware
mkdir espressif
cd espressif
git clone https://github.com/espressif/arduino-esp32.git esp32
pushd esp32
# Set custom warnings for all builds (i.e. could add -Wextra at some point)
# Set custom warnings for all builds
echo "compiler.c.extra_flags=-Wall -Wextra -Werror $debug_flags" > platform.local.txt
echo "compiler.cpp.extra_flags=-Wall -Wextra -Werror $debug_flags" >> platform.local.txt
echo -e "\n----platform.local.txt----"
cat platform.local.txt
git submodule init
git submodule update
git submodule update --init
cd tools
python3 get.py
export PATH="$ide_path/hardware/espressif/esp32/tools/xtensa-esp32-elf/bin/:$PATH"
popd
cd esp32
}
function install_arduino()
{
# Install Arduino IDE and required libraries
echo -e "travis_fold:start:sketch_test_env_prepare"
cd $TRAVIS_BUILD_DIR
install_ide $HOME/arduino_ide $TRAVIS_BUILD_DIR
cd "$GITHUB_WORKSPACE"
install_ide "$HOME/arduino_ide" "$GITHUB_WORKSPACE"
which arduino
cd $TRAVIS_BUILD_DIR
cd "$GITHUB_WORKSPACE"
install_libraries
echo -e "travis_fold:end:sketch_test_env_prepare"
}
function build_sketches_with_arduino()
{
# Compile sketches
echo -e "travis_fold:start:sketch_test"
build_sketches $HOME/arduino_ide $HOME/Arduino/libraries "-l $HOME/Arduino/libraries"
echo -e "travis_fold:end:sketch_test"
# Generate size report
echo -e "travis_fold:start:size_report"
cat size.log
echo -e "travis_fold:end:size_report"
}
set -e
if [ "$BUILD_MOD" == "" ]; then
export BUILD_MOD=1
export BUILD_REM=0
fi
export cache_dir=$(mktemp -d)
if [ "$BUILD_TYPE" = "build" ]; then
export BUILD_PY="hardware/esp8266com/esp8266/tools/build.py -b generic -s 4M1M -v -k "
install_arduino
install_esp8266 "$HOME/arduino_ide"
build_sketches_with_arduino
source "$HOME/arduino_ide/hardware/esp8266com/esp8266/tests/common.sh"
export ESP8266_ARDUINO_SKETCHES=$(find $HOME/Arduino/libraries/ESP8266Audio -name *.ino | sort)
# ESP8266 scripts now expect tools in wrong spot. Use simple and dumb fix
mkdir -p "$HOME/work/ESP8266Audio/ESP8266Audio"
ln -s "$HOME/arduino_ide/hardware/esp8266com/esp8266/tools" "$HOME/work/ESP8266Audio/ESP8266Audio/tools"
build_sketches "$TRAVIS_BUILD_DIR" "$HOME/arduino_ide" "$HOME/arduino_ide/hardware" "$HOME/Arduino/libraries" "$BUILD_MOD" "$BUILD_REM" "lm2f"
elif [ "$BUILD_TYPE" = "build_esp32" ]; then
install_arduino
install_esp32 "$HOME/arduino_ide"
export ide_path=$HOME/arduino_ide
export FQBN="espressif:esp32:esp32:PSRAM=enabled,PartitionScheme=huge_app"
export GITHUB_WORKSPACE="$TRAVIS_BUILD_DIR"
export GITHUB_REPOSITORY="$TRAVIS_REPO_SLUG"
source $ide_path/hardware/espressif/esp32/.github/scripts/install-arduino-ide.sh
source $ide_path/hardware/espressif/esp32/.github/scripts/install-arduino-core-esp32.sh
build_sketches "$FQBN" "$HOME/Arduino/libraries" "$BUILD_REM" "$BUILD_MOD"
mkdir -p "$GITHUB_WORKSPACE/hardware"
ln -s "$GITHUB_WORKSPACE/../" "$GITHUB_WORKSPACE/libraries"
source "$HOME/arduino_ide/hardware/espressif/esp32/.github/scripts/sketch_utils.sh" chunk_build -ai "$HOME/arduino_ide" -au "$GITHUB_WORKSPACE" -fqbn "$FQBN" -t esp32 -p "$GITHUB_WORKSPACE" -i $BUILD_REM -m $BUILD_MOD
elif [ "$BUILD_TYPE" = "build_rp2040" ]; then
install_arduino
install_rp2040 "$HOME/arduino_ide"
source "$HOME/arduino_ide/hardware/pico/rp2040/tests/common.sh"
build_sketches "$HOME/arduino_ide" "$TRAVIS_BUILD_DIR" "-l $HOME/Arduino/libraries" "$BUILD_MOD" "$BUILD_REM"
fi