From e84124f035836f7556fb2c21d9da03b97122b407 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 27 Dec 2021 14:24:58 +0100 Subject: [PATCH] updated Audio libs --- .../.github/workflows/pr-or-master-push.yml | 24 +++ lib/lib_audio/ESP8266Audio/README.md | 16 +- .../PlayFLAC-SD-SPDIF/PlayFLAC-SD-SPDIF.ino | 2 +- .../PlayMIDIFromSPIFFS/PlayMIDIFromSPIFFS.ino | 1 + .../PlayWAVFromFunction.ino | 2 +- .../StreamMP3FromHTTPToSPDIF.ino | 142 ++++++++++++++++++ lib/lib_audio/ESP8266Audio/library.json | 2 +- lib/lib_audio/ESP8266Audio/library.properties | 2 +- .../src/AudioFileSourceFunction.cpp | 2 +- .../src/AudioFileSourceFunction.h | 2 +- .../src/AudioFileSourceICYStream.cpp | 1 + .../src/AudioFileSourceLittleFS.h | 4 - .../src/AudioFileSourceSPIRAMBuffer.cpp | 2 +- .../ESP8266Audio/src/AudioGeneratorMIDI.cpp | 8 +- .../ESP8266Audio/src/AudioGeneratorMOD.cpp | 10 +- .../ESP8266Audio/src/AudioGeneratorMOD.h | 4 +- .../ESP8266Audio/src/AudioOutputI2S.cpp | 64 ++++++-- .../ESP8266Audio/src/AudioOutputI2S.h | 2 + .../ESP8266Audio/src/AudioOutputI2SNoDAC.cpp | 24 +-- .../ESP8266Audio/src/AudioOutputSPDIF.cpp | 10 +- .../ESP8266Audio/src/AudioOutputSPDIF.h | 2 +- .../ESP8266Audio/src/AudioOutputSTDIO.cpp | 5 + .../ESP8266Audio/src/AudioOutputULP.cpp | 2 +- .../src/driver/SinglePinI2SDriver.cpp | 8 +- .../ESP8266Audio/src/libflac/stream_decoder.c | 12 +- .../ESP8266Audio/src/libhelix-aac/assembly.h | 2 +- .../ESP8266Audio/src/libhelix-mp3/RPSL.txt | 2 +- .../ESP8266Audio/src/libhelix-mp3/assembly.h | 4 +- .../ESP8266Audio/src/libhelix-mp3/scalfact.c | 2 +- .../ESP8266Audio/src/libogg/README.md | 4 +- .../src/libtinysoundfont/README.ESP8266 | 2 +- .../ESP8266Audio/src/libtinysoundfont/tsf.h | 4 +- .../ESP8266Audio/src/opusfile/opusfile.h | 4 +- lib/lib_audio/ESP8266Audio/tests/common.sh | 2 +- .../ESP8266Audio/tests/host/Makefile | 10 +- lib/lib_audio/ESP8266Audio/tests/host/mod.cpp | 26 ++++ lib/lib_audio/ESP8266SAM/README.md | 4 + .../examples/SpeakNoDac/SpeakNoDac.ino | 20 +++ .../examples/remoteSAM/remoteSAM.ino | 129 ++++++++++++++++ lib/lib_audio/ESP8266SAM/library.json | 7 +- lib/lib_audio/ESP8266SAM/library.properties | 8 +- lib/lib_audio/ESP8266SAM/src/ESP8266SAM.h | 5 +- lib/lib_audio/ESP8266SAM/src/ReciterTabs.h | 4 +- lib/lib_audio/ESP8266SAM/src/RenderTabs.h | 6 +- lib/lib_audio/ESP8266SAM/src/SamTabs.h | 4 +- .../src/{samdebug.c => esp8266sam_debug.c} | 0 .../src/{samdebug.h => esp8266sam_debug.h} | 6 +- lib/lib_audio/ESP8266SAM/src/reciter.c | 4 +- lib/lib_audio/ESP8266SAM/src/render.c | 7 +- lib/lib_audio/ESP8266SAM/src/sam.c | 128 ++++++++-------- 50 files changed, 574 insertions(+), 173 deletions(-) create mode 100644 lib/lib_audio/ESP8266Audio/examples/StreamMP3FromHTTPToSPDIF/StreamMP3FromHTTPToSPDIF.ino create mode 100644 lib/lib_audio/ESP8266Audio/tests/host/mod.cpp create mode 100644 lib/lib_audio/ESP8266SAM/examples/SpeakNoDac/SpeakNoDac.ino create mode 100644 lib/lib_audio/ESP8266SAM/examples/remoteSAM/remoteSAM.ino rename lib/lib_audio/ESP8266SAM/src/{samdebug.c => esp8266sam_debug.c} (100%) rename lib/lib_audio/ESP8266SAM/src/{samdebug.h => esp8266sam_debug.h} (79%) diff --git a/lib/lib_audio/ESP8266Audio/.github/workflows/pr-or-master-push.yml b/lib/lib_audio/ESP8266Audio/.github/workflows/pr-or-master-push.yml index 88d6fca71..fcbd0952e 100644 --- a/lib/lib_audio/ESP8266Audio/.github/workflows/pr-or-master-push.yml +++ b/lib/lib_audio/ESP8266Audio/.github/workflows/pr-or-master-push.yml @@ -86,3 +86,27 @@ jobs: 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 + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: arduino/arduino-lint-action@v1 + with: + library-manager: 'update' + +# Validate orthography + code-spell: + name: Check spelling + runs-on: ubuntu-latest + defaults: + run: + shell: bash + steps: + - uses: actions/checkout@v2 + with: + submodules: true + - name: Run codespell + uses: codespell-project/actions-codespell@master + with: + skip: ./src/libmad,./src/libhelix-aac,./src/libopus + ignore_words_list: ESP8266,esp8266,esp,dout,DOUT,ser,ans,inout,numer,hist diff --git a/lib/lib_audio/ESP8266Audio/README.md b/lib/lib_audio/ESP8266Audio/README.md index f243db52a..0b3ab8d5a 100644 --- a/lib/lib_audio/ESP8266Audio/README.md +++ b/lib/lib_audio/ESP8266Audio/README.md @@ -31,7 +31,9 @@ JohannesMTC has built a similar project especially for model trains: https://git 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 http://home.kpn.nl/bderogee1980/projects/linear_clock/linear_clock.html +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. @@ -100,7 +102,7 @@ AudioFileSourcePROGMEM: Reads a file from a PROGMEM array. Under UNIX you can AudioFileSourceHTTPStream: Simple implementation of a streaming HTTP reader for ShoutCast-type MP3 streaming. Not yet resilient, and at 44.1khz 128bit stutters due to CPU limitations, but it works more or less. ## AudioFileSourceBuffer - Double buffering, useful for HTTP streams -AudioFileSourceBuffer is an input source that simpy adds an additional RAM buffer of the output of any other AudioFileSource. This is particularly useful for web streaming where you need to have 1-2 packets in memory to ensure hiccup-free playback. +AudioFileSourceBuffer is an input source that simply adds an additional RAM buffer of the output of any other AudioFileSource. This is particularly useful for web streaming where you need to have 1-2 packets in memory to ensure hiccup-free playback. Create your standard input file source, create the buffer with the original source as its input, and pass this buffer object to the generator. ```cpp @@ -158,7 +160,15 @@ AudioOutputSPIFFSWAV: Writes a binary WAV format with headers to a SPIFFS files AudioOutputNull: Just dumps samples to /dev/null. Used for speed testing as it doesn't artificially limit the AudioGenerator output speed since there are no buffers to fill/drain. ## I2S DACs -I've used both the Adafruit [I2S +3W amp DAC](https://www.adafruit.com/product/3006) and a generic PCM5102 based DAC with success. The biggest problems I've seen from users involve pinouts from the ESP8266 for GPIO and hooking up all necessary pins on the DAC board. +I've used both the Adafruit [I2S +3W amp DAC](https://www.adafruit.com/product/3006) and a generic PCM5102 based DAC with success. The biggest problems I've seen from users involve pinouts from the ESP8266 for GPIO and hooking up all necessary pins on the DAC board. The essential pins are: + +I2S pin | Common label* | ESP8266 pin +--------|---------------|------------- +LRC | D4 | GPIO2 +BCLK | D8 | GPIO15 +DIN | RX | GPIO3 + +\* The "common label" column applies to common NodeMCU and D1 Mini development boards. Unfortunately some manufacturers use different mappings so the labels listed here might not apply to your particular model. ### Adafruit I2S DAC This is quite simple and only needs the GND, VIN, LRC, BCLK< and DIN pins to be wired. Be sure to use +5V on the VIN to get the loudest sound. See the [Adafruit example page](https://learn.adafruit.com/adafruit-max98357-i2s-class-d-mono-amp) for more info. diff --git a/lib/lib_audio/ESP8266Audio/examples/PlayFLAC-SD-SPDIF/PlayFLAC-SD-SPDIF.ino b/lib/lib_audio/ESP8266Audio/examples/PlayFLAC-SD-SPDIF/PlayFLAC-SD-SPDIF.ino index 3c127883b..50b0ade33 100644 --- a/lib/lib_audio/ESP8266Audio/examples/PlayFLAC-SD-SPDIF/PlayFLAC-SD-SPDIF.ino +++ b/lib/lib_audio/ESP8266Audio/examples/PlayFLAC-SD-SPDIF/PlayFLAC-SD-SPDIF.ino @@ -8,7 +8,7 @@ // Espressif Audio Development Framework at: // https://docs.espressif.com/projects/esp-adf/en/latest/design-guide/audio-samples.html // -// On ESP8266 you might need to reencode FLAC files with max '-2' compression level +// On ESP8266 you might need to re-encode FLAC files with max '-2' compression level // (i.e. 1152 maximum block size) or you will run out of memory. FLAC files will be // slightly bigger but you don't loose audio quality with reencoding (lossles codec). diff --git a/lib/lib_audio/ESP8266Audio/examples/PlayMIDIFromSPIFFS/PlayMIDIFromSPIFFS.ino b/lib/lib_audio/ESP8266Audio/examples/PlayMIDIFromSPIFFS/PlayMIDIFromSPIFFS.ino index dcfa8f983..da9f685c3 100644 --- a/lib/lib_audio/ESP8266Audio/examples/PlayMIDIFromSPIFFS/PlayMIDIFromSPIFFS.ino +++ b/lib/lib_audio/ESP8266Audio/examples/PlayMIDIFromSPIFFS/PlayMIDIFromSPIFFS.ino @@ -25,6 +25,7 @@ void setup() WiFi.mode(WIFI_OFF); Serial.begin(115200); + SPIFFS.begin(); Serial.println("Starting up...\n"); audioLogger = &Serial; diff --git a/lib/lib_audio/ESP8266Audio/examples/PlayWAVFromFunction/PlayWAVFromFunction.ino b/lib/lib_audio/ESP8266Audio/examples/PlayWAVFromFunction/PlayWAVFromFunction.ino index fe0cc896d..9af90e0dc 100644 --- a/lib/lib_audio/ESP8266Audio/examples/PlayWAVFromFunction/PlayWAVFromFunction.ino +++ b/lib/lib_audio/ESP8266Audio/examples/PlayWAVFromFunction/PlayWAVFromFunction.ino @@ -44,7 +44,7 @@ void setup() { // param : float (current time [sec] of the song) // return : float (the amplitude of sound which varies from -1.f to +1.f) // - // sound function can be registerd only one or the same number with channels + // sound function can be registered only one or the same number with channels // if the channels > 1 && the number of function == 1, // same function are used to generate the sound in every channel // diff --git a/lib/lib_audio/ESP8266Audio/examples/StreamMP3FromHTTPToSPDIF/StreamMP3FromHTTPToSPDIF.ino b/lib/lib_audio/ESP8266Audio/examples/StreamMP3FromHTTPToSPDIF/StreamMP3FromHTTPToSPDIF.ino new file mode 100644 index 000000000..ef5429083 --- /dev/null +++ b/lib/lib_audio/ESP8266Audio/examples/StreamMP3FromHTTPToSPDIF/StreamMP3FromHTTPToSPDIF.ino @@ -0,0 +1,142 @@ +#include + +#ifdef ESP32 + #include +#else + #include +#endif +#include "AudioFileSourceICYStream.h" +#include "AudioFileSourceBuffer.h" +#include "AudioGeneratorMP3.h" +//#include "AudioOutputI2SNoDAC.h" +#include "AudioOutputSPDIF.h" + +// +// Stream MP3 from HTTP to SPDIF +// + +// To run, set your ESP8266 build to 160MHz, update the SSID info, and upload. + +// Note: +// If using ESP8266 NodeMCU connect LED to RX pin and GND pin + +// Enter your WiFi setup here: +#ifndef STASSID +#define STASSID "your-ssid" +#define STAPSK "your-password" +#endif + +const char* ssid = STASSID; +const char* password = STAPSK; + +// Examples URLs +//const char *URL="http://kvbstreams.dyndns.org:8000/wkvi-am"; + +// Italian Rock Radio +const char *URL="http://streamingv2.shoutcast.com/radiofreccia"; + +// Stream URL of Logitech Media Server, aka LMS, Version: 8.2.0 (August 2021) +// const char *URL="http://192.168.1.121:9000/stream.mp3"; + +AudioGeneratorMP3 *mp3; +AudioFileSourceICYStream *file; +AudioFileSourceBuffer *buff; + +// Output device is SPDIF +AudioOutputSPDIF *out; + + +// Called when a metadata event occurs (i.e. an ID3 tag, an ICY block, etc. +void MDCallback(void *cbData, const char *type, bool isUnicode, const char *string) +{ + const char *ptr = reinterpret_cast(cbData); + (void) isUnicode; // Punt this ball for now + // Note that the type and string may be in PROGMEM, so copy them to RAM for printf + char s1[32], s2[64]; + strncpy_P(s1, type, sizeof(s1)); + s1[sizeof(s1)-1]=0; + strncpy_P(s2, string, sizeof(s2)); + s2[sizeof(s2)-1]=0; + Serial.printf("METADATA(%s) '%s' = '%s'\n", ptr, s1, s2); + Serial.flush(); +} + +// Called when there's a warning or error (like a buffer underflow or decode hiccup) +void StatusCallback(void *cbData, int code, const char *string) +{ + const char *ptr = reinterpret_cast(cbData); + // Note that the string may be in PROGMEM, so copy it to RAM for printf + char s1[64]; + strncpy_P(s1, string, sizeof(s1)); + s1[sizeof(s1)-1]=0; + Serial.printf("STATUS(%s) '%d' = '%s'\n", ptr, code, s1); + Serial.flush(); +} + + +void setup() +{ + Serial.begin(115200); + delay(1000); + Serial.println("Connecting to WiFi"); + + WiFi.disconnect(); + WiFi.softAPdisconnect(true); + WiFi.mode(WIFI_STA); + + WiFi.begin(ssid, password); + + // Try forever + while (WiFi.status() != WL_CONNECTED) { + Serial.println("...Connecting to WiFi"); + delay(1000); + } + Serial.println("Connected"); + + audioLogger = &Serial; + file = new AudioFileSourceICYStream(URL); + + // Commented out for performance issues with high rate MP3 stream + //file->RegisterMetadataCB(MDCallback, (void*)"ICY"); + + buff = new AudioFileSourceBuffer(file, 4096); // Doubled form default 2048 + + // Commented out for performance issues with high rate MP3 stream + //buff->RegisterStatusCB(StatusCallback, (void*)"buffer"); + + // Set SPDIF output + out = new AudioOutputSPDIF(); + mp3 = new AudioGeneratorMP3(); + + // Commented out for performance issues with high rate MP3 stream + //mp3->RegisterStatusCB(StatusCallback, (void*)"mp3"); + + mp3->begin(buff, out); +} + + +void loop() +{ + // Commented out + //static int lastms = 0; + + if (mp3->isRunning()) { + /* Commented out + if (millis()-lastms > 1000) { + lastms = millis(); + Serial.printf("Running for %d ms...\n", lastms); + Serial.flush(); + } + */ + if (!mp3->loop()) { + mp3->stop(); + } + } else { + Serial.printf("MP3 done\n"); + + // Restart ESP when streaming is done or errored + delay(10000); + + ESP.restart(); + } +} diff --git a/lib/lib_audio/ESP8266Audio/library.json b/lib/lib_audio/ESP8266Audio/library.json index 139291880..ddbb6d634 100644 --- a/lib/lib_audio/ESP8266Audio/library.json +++ b/lib/lib_audio/ESP8266Audio/library.json @@ -14,7 +14,7 @@ "type": "git", "url": "https://github.com/earlephilhower/ESP8266Audio" }, - "version": "1.9.2", + "version": "1.9.5", "homepage": "https://github.com/earlephilhower/ESP8266Audio", "frameworks": "Arduino", "examples": [ diff --git a/lib/lib_audio/ESP8266Audio/library.properties b/lib/lib_audio/ESP8266Audio/library.properties index 111915c1c..85a99c0e3 100644 --- a/lib/lib_audio/ESP8266Audio/library.properties +++ b/lib/lib_audio/ESP8266Audio/library.properties @@ -1,5 +1,5 @@ name=ESP8266Audio -version=1.9.2 +version=1.9.5 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 diff --git a/lib/lib_audio/ESP8266Audio/src/AudioFileSourceFunction.cpp b/lib/lib_audio/ESP8266Audio/src/AudioFileSourceFunction.cpp index 9e86eff21..885defa4e 100644 --- a/lib/lib_audio/ESP8266Audio/src/AudioFileSourceFunction.cpp +++ b/lib/lib_audio/ESP8266Audio/src/AudioFileSourceFunction.cpp @@ -1,6 +1,6 @@ /* AudioFileSourceFunction - Audio ouptut generator which can generate WAV file data from function + Audio output generator which can generate WAV file data from function Copyright (C) 2021 Hideaki Tai diff --git a/lib/lib_audio/ESP8266Audio/src/AudioFileSourceFunction.h b/lib/lib_audio/ESP8266Audio/src/AudioFileSourceFunction.h index 6c41229ae..94b88d6fb 100644 --- a/lib/lib_audio/ESP8266Audio/src/AudioFileSourceFunction.h +++ b/lib/lib_audio/ESP8266Audio/src/AudioFileSourceFunction.h @@ -1,6 +1,6 @@ /* AudioFileSourceFunction - Audio ouptut generator which can generate WAV file data from function + Audio output generator which can generate WAV file data from function Copyright (C) 2021 Hideaki Tai diff --git a/lib/lib_audio/ESP8266Audio/src/AudioFileSourceICYStream.cpp b/lib/lib_audio/ESP8266Audio/src/AudioFileSourceICYStream.cpp index bbc348d53..25e641705 100644 --- a/lib/lib_audio/ESP8266Audio/src/AudioFileSourceICYStream.cpp +++ b/lib/lib_audio/ESP8266Audio/src/AudioFileSourceICYStream.cpp @@ -49,6 +49,7 @@ bool AudioFileSourceICYStream::open(const char *url) http.addHeader("Icy-MetaData", "1"); http.collectHeaders( hdr, 4 ); http.setReuse(true); + http.setFollowRedirects(HTTPC_FORCE_FOLLOW_REDIRECTS); int code = http.GET(); if (code != HTTP_CODE_OK) { http.end(); diff --git a/lib/lib_audio/ESP8266Audio/src/AudioFileSourceLittleFS.h b/lib/lib_audio/ESP8266Audio/src/AudioFileSourceLittleFS.h index 27d94bb8b..b57b89fa3 100644 --- a/lib/lib_audio/ESP8266Audio/src/AudioFileSourceLittleFS.h +++ b/lib/lib_audio/ESP8266Audio/src/AudioFileSourceLittleFS.h @@ -21,8 +21,6 @@ #ifndef _AUDIOFILESOURCESPIFFS_H #define _AUDIOFILESOURCESPIFFS_H -#ifndef ESP32 // No LittleFS there, yet - #include #include @@ -39,5 +37,3 @@ class AudioFileSourceLittleFS : public AudioFileSourceFS #endif -#endif - diff --git a/lib/lib_audio/ESP8266Audio/src/AudioFileSourceSPIRAMBuffer.cpp b/lib/lib_audio/ESP8266Audio/src/AudioFileSourceSPIRAMBuffer.cpp index 2c9eb3b96..475afa4d0 100644 --- a/lib/lib_audio/ESP8266Audio/src/AudioFileSourceSPIRAMBuffer.cpp +++ b/lib/lib_audio/ESP8266Audio/src/AudioFileSourceSPIRAMBuffer.cpp @@ -105,7 +105,7 @@ uint32_t AudioFileSourceSPIRAMBuffer::read(void *data, uint32_t len) } // Read up to the entire buffer from RAM - uint32_t toReadFromBuffer = std::min(len, writePtr - readPtr); + uint32_t toReadFromBuffer = std::min(len, (uint32_t)(writePtr - readPtr)); uint8_t *ptr = reinterpret_cast(data); if (toReadFromBuffer > 0) { #ifdef FAKERAM diff --git a/lib/lib_audio/ESP8266Audio/src/AudioGeneratorMIDI.cpp b/lib/lib_audio/ESP8266Audio/src/AudioGeneratorMIDI.cpp index e3be2b2d0..5f1c5f3a3 100644 --- a/lib/lib_audio/ESP8266Audio/src/AudioGeneratorMIDI.cpp +++ b/lib/lib_audio/ESP8266Audio/src/AudioGeneratorMIDI.cpp @@ -1,6 +1,6 @@ /* AudioGeneratorMIDI - Audio output generator that plays MIDI files using a SF2 SoundFont + Audio output generator that plays MIDI files using an SF2 SoundFont Copyright (C) 2017 Earle F. Philhower, III @@ -172,7 +172,7 @@ unsigned int AudioGeneratorMIDI::buffer_int32 (int offset) { unsigned long AudioGeneratorMIDI::get_varlen (int *ptr) { /* Get a 1-4 byte variable-length value and adjust the pointer past it. - These are a succession of 7-bit values with a MSB bit of zero marking the end */ + These are a succession of 7-bit values with an MSB bit of zero marking the end */ unsigned long val; int i, byte; @@ -331,7 +331,7 @@ note_off: } -// Open file, parse headers, get ready tio process MIDI +// Open file, parse headers, get ready to process MIDI void AudioGeneratorMIDI::PrepareMIDI(AudioFileSource *src) { MakeStreamFromAFS(src, &afsMIDI); @@ -364,7 +364,7 @@ void AudioGeneratorMIDI::PrepareMIDI(AudioFileSource *src) int AudioGeneratorMIDI::PlayMIDI() { /* Continue processing all tracks, in an order based on the simulated time. - This is not unlike multiway merging used for tape sorting algoritms in the 50's! */ + This is not unlike multiway merging used for tape sorting algorithms in the 50's! */ do { /* while there are still track notes to process */ static struct track_status *trk; diff --git a/lib/lib_audio/ESP8266Audio/src/AudioGeneratorMOD.cpp b/lib/lib_audio/ESP8266Audio/src/AudioGeneratorMOD.cpp index f42154f85..b47b28396 100644 --- a/lib/lib_audio/ESP8266Audio/src/AudioGeneratorMOD.cpp +++ b/lib/lib_audio/ESP8266Audio/src/AudioGeneratorMOD.cpp @@ -124,7 +124,7 @@ bool AudioGeneratorMOD::begin(AudioFileSource *source, AudioOutput *out) UpdateAmiga(); for (int i = 0; i < CHANNELS; i++) { - FatBuffer.channels[i] = reinterpret_cast(malloc(fatBufferSize)); + FatBuffer.channels[i] = reinterpret_cast(calloc(fatBufferSize, 1)); if (!FatBuffer.channels[i]) { stop(); return false; @@ -565,7 +565,7 @@ bool AudioGeneratorMOD::ProcessRow() Mixer.channelFrequency[channel] = Player.amiga / Player.lastAmigaPeriod[channel]; if (note != NONOTE) - Mixer.channelSampleOffset[channel] = sampleOffset << DIVIDER; + Mixer.channelSampleOffset[channel] = sampleOffset << FIXED_DIVIDER; if (sampleNumber) Mixer.channelSampleNumber[channel] = Player.lastSampleNumber[channel]; @@ -757,12 +757,12 @@ void AudioGeneratorMOD::GetSample(int16_t sample[2]) if (!Mixer.channelVolume[channel]) continue; samplePointer = Mixer.sampleBegin[Mixer.channelSampleNumber[channel]] + - (Mixer.channelSampleOffset[channel] >> DIVIDER); + (Mixer.channelSampleOffset[channel] >> FIXED_DIVIDER); if (Mixer.sampleLoopLength[Mixer.channelSampleNumber[channel]]) { if (samplePointer >= Mixer.sampleLoopEnd[Mixer.channelSampleNumber[channel]]) { - Mixer.channelSampleOffset[channel] -= Mixer.sampleLoopLength[Mixer.channelSampleNumber[channel]] << DIVIDER; + Mixer.channelSampleOffset[channel] -= Mixer.sampleLoopLength[Mixer.channelSampleNumber[channel]] << FIXED_DIVIDER; samplePointer -= Mixer.sampleLoopLength[Mixer.channelSampleNumber[channel]]; } @@ -801,7 +801,7 @@ void AudioGeneratorMOD::GetSample(int16_t sample[2]) out = current; // Integer linear interpolation - out += (next - current) * (Mixer.channelSampleOffset[channel] & ((1 << DIVIDER) - 1)) >> DIVIDER; + out += (next - current) * (Mixer.channelSampleOffset[channel] & ((1 << FIXED_DIVIDER) - 1)) >> FIXED_DIVIDER; // Upscale to BITDEPTH out <<= BITDEPTH - 8; diff --git a/lib/lib_audio/ESP8266Audio/src/AudioGeneratorMOD.h b/lib/lib_audio/ESP8266Audio/src/AudioGeneratorMOD.h index 87fac18e9..060037750 100644 --- a/lib/lib_audio/ESP8266Audio/src/AudioGeneratorMOD.h +++ b/lib/lib_audio/ESP8266Audio/src/AudioGeneratorMOD.h @@ -56,14 +56,14 @@ class AudioGeneratorMOD : public AudioGenerator enum {BITDEPTH = 15}; int sampleRate; int fatBufferSize; //(6*1024) // File system buffers per-CHANNEL (i.e. total mem required is 4 * FATBUFFERSIZE) - enum {DIVIDER = 10}; // Fixed-point mantissa used for integer arithmetic + enum {FIXED_DIVIDER = 10}; // Fixed-point mantissa used for integer arithmetic int stereoSeparation; //STEREOSEPARATION = 32; // 0 (max) to 64 (mono) bool usePAL; // Hz = 7093789 / (amigaPeriod * 2) for PAL // Hz = 7159091 / (amigaPeriod * 2) for NTSC int AMIGA; - void UpdateAmiga() { AMIGA = ((usePAL?7159091:7093789) / 2 / sampleRate << DIVIDER); } + void UpdateAmiga() { AMIGA = ((usePAL?7159091:7093789) / 2 / sampleRate << FIXED_DIVIDER); } enum {ROWS = 64, SAMPLES = 31, CHANNELS = 4, NONOTE = 0xFFFF, NONOTE8 = 0xff }; diff --git a/lib/lib_audio/ESP8266Audio/src/AudioOutputI2S.cpp b/lib/lib_audio/ESP8266Audio/src/AudioOutputI2S.cpp index 5e524894d..0eb3c0da7 100644 --- a/lib/lib_audio/ESP8266Audio/src/AudioOutputI2S.cpp +++ b/lib/lib_audio/ESP8266Audio/src/AudioOutputI2S.cpp @@ -1,7 +1,7 @@ /* AudioOutputI2S Base class for I2S interface port - + Copyright (C) 2017 Earle F. Philhower, III This program is free software: you can redistribute it and/or modify @@ -21,12 +21,10 @@ #include #ifdef ESP32 #include "driver/i2s.h" -#elif defined(ARDUINO_ARCH_RP2040) || defined(ESP8266) - #ifdef ARDUINO_ESP8266_MAJOR //this define was added in ESP8266 Arduino Core version v3.0.1 - #include "core_esp8266_i2s.h" //for Arduino core >= 3.0.1 - #else - #include "i2s.h" //for Arduino core <= 3.0.0 - #endif +#elif defined(ARDUINO_ARCH_RP2040) || ARDUINO_ESP8266_MAJOR >= 3 + #include +#elif ARDUINO_ESP8266_MAJOR < 3 + #include #endif #include "AudioOutputI2S.h" @@ -44,6 +42,7 @@ AudioOutputI2S::AudioOutputI2S(int port, int output_mode, int dma_buf_count, int //set defaults mono = false; + lsb_justified = false; bps = 16; channels = 2; hertz = 44100; @@ -150,6 +149,12 @@ bool AudioOutputI2S::SetOutputModeMono(bool mono) return true; } +bool AudioOutputI2S::SetLsbJustified(bool lsbJustified) +{ + this->lsb_justified = lsbJustified; + return true; +} + bool AudioOutputI2S::begin(bool txDAC) { #ifdef ESP32 @@ -170,17 +175,41 @@ bool AudioOutputI2S::begin(bool txDAC) i2s_mode_t mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX); if (output_mode == INTERNAL_DAC) { +#if CONFIG_IDF_TARGET_ESP32 mode = (i2s_mode_t)(mode | I2S_MODE_DAC_BUILT_IN); +#else + return false; +#endif } else if (output_mode == INTERNAL_PDM) { +#if CONFIG_IDF_TARGET_ESP32 mode = (i2s_mode_t)(mode | I2S_MODE_PDM); +#else + return false; +#endif } - i2s_comm_format_t comm_fmt = (i2s_comm_format_t)(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB); + i2s_comm_format_t comm_fmt; if (output_mode == INTERNAL_DAC) { - comm_fmt = (i2s_comm_format_t)I2S_COMM_FORMAT_I2S_MSB; +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) + comm_fmt = (i2s_comm_format_t) I2S_COMM_FORMAT_STAND_MSB; +#else + comm_fmt = (i2s_comm_format_t) I2S_COMM_FORMAT_I2S_MSB; +#endif + } + else if (lsb_justified) + { + comm_fmt = (i2s_comm_format_t) (I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_LSB); + } + else + { +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) + comm_fmt = (i2s_comm_format_t) (I2S_COMM_FORMAT_STAND_I2S); +#else + comm_fmt = (i2s_comm_format_t) (I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB); +#endif } i2s_config_t i2s_config_dac = { @@ -191,7 +220,7 @@ bool AudioOutputI2S::begin(bool txDAC) .communication_format = comm_fmt, .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, // lowest interrupt priority .dma_buf_count = dma_buf_count, - .dma_buf_len = 64, + .dma_buf_len = 128, .use_apll = use_apll // Use audio PLL }; audioLogger->printf("+%d %p\n", portNo, &i2s_config_dac); @@ -201,8 +230,12 @@ bool AudioOutputI2S::begin(bool txDAC) } if (output_mode == INTERNAL_DAC || output_mode == INTERNAL_PDM) { +#if CONFIG_IDF_TARGET_ESP32 i2s_set_pin((i2s_port_t)portNo, NULL); i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN); +#else + return false; +#endif } else { @@ -273,11 +306,12 @@ bool AudioOutputI2S::ConsumeSample(int16_t sample[2]) { s32 = ((Amplify(ms[RIGHTCHANNEL])) << 16) | (Amplify(ms[LEFTCHANNEL]) & 0xffff); } -// Deprecated. Use i2s_write +//"i2s_write_bytes" has been removed in the ESP32 Arduino 2.0.0, use "i2s_write" instead. // return i2s_write_bytes((i2s_port_t)portNo, (const char *)&s32, sizeof(uint32_t), 0); - size_t bytes_written; - i2s_write((i2s_port_t)portNo, (const char*)&s32, sizeof(uint32_t), &bytes_written, 0); - return bytes_written; + + size_t i2s_bytes_written; + i2s_write((i2s_port_t)portNo, (const char*)&s32, sizeof(uint32_t), &i2s_bytes_written, 0); + return i2s_bytes_written; #elif defined(ESP8266) 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 @@ -290,7 +324,7 @@ void AudioOutputI2S::flush() { #ifdef ESP32 // makes sure that all stored DMA samples are consumed / played - int buffersize = 64 * this->dma_buf_count; + int buffersize = 128 * this->dma_buf_count; int16_t samples[2] = {0x0, 0x0}; for (int i = 0; i < buffersize; i++) { diff --git a/lib/lib_audio/ESP8266Audio/src/AudioOutputI2S.h b/lib/lib_audio/ESP8266Audio/src/AudioOutputI2S.h index 90370dc27..b3f621d28 100644 --- a/lib/lib_audio/ESP8266Audio/src/AudioOutputI2S.h +++ b/lib/lib_audio/ESP8266Audio/src/AudioOutputI2S.h @@ -44,6 +44,7 @@ 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 protected: bool SetPinout(); @@ -51,6 +52,7 @@ class AudioOutputI2S : public AudioOutput uint8_t portNo; int output_mode; bool mono; + int lsb_justified; bool i2sOn; int dma_buf_count; int use_apll; diff --git a/lib/lib_audio/ESP8266Audio/src/AudioOutputI2SNoDAC.cpp b/lib/lib_audio/ESP8266Audio/src/AudioOutputI2SNoDAC.cpp index 116d9ac74..976d73c77 100644 --- a/lib/lib_audio/ESP8266Audio/src/AudioOutputI2SNoDAC.cpp +++ b/lib/lib_audio/ESP8266Audio/src/AudioOutputI2SNoDAC.cpp @@ -1,7 +1,7 @@ /* AudioOutputI2SNoDAC Audio player using SW delta-sigma to generate "analog" on I2S data - + Copyright (C) 2017 Earle F. Philhower, III This program is free software: you can redistribute it and/or modify @@ -21,12 +21,10 @@ #include #ifdef ESP32 #include "driver/i2s.h" -#elif defined(ARDUINO_ARCH_RP2040) || defined(ESP8266) - #ifdef ARDUINO_ESP8266_MAJOR //this define was added in ESP8266 Arduino Core version v3.0.1 - #include "core_esp8266_i2s.h" //for Arduino core >= 3.0.1 - #else - #include "i2s.h" //for Arduino core <= 3.0.0 - #endif +#elif defined(ARDUINO_ARCH_RP2040) || ARDUINO_ESP8266_MAJOR >= 3 + #include +#elif ARDUINO_ESP8266_MAJOR < 3 + #include #endif #include "AudioOutputI2SNoDAC.h" @@ -70,7 +68,7 @@ void AudioOutputI2SNoDAC::DeltaSigma(int16_t sample[2], uint32_t dsBuff[8]) for (int j = 0; j < oversample32; j++) { uint32_t bits = 0; // The bits we convert the sample into, MSB to go on the wire first - + for (int i = 32; i > 0; i--) { bits = bits << 1; if (cumErr < 0) { @@ -99,12 +97,14 @@ bool AudioOutputI2SNoDAC::ConsumeSample(int16_t sample[2]) // Either send complete pulse stream or nothing #ifdef ESP32 -// Deprecated. Use i2s_write +//"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 bytes_written; - i2s_write((i2s_port_t)portNo, (const char *)dsBuff, sizeof(uint32_t) * (oversample/32), &bytes_written, 0); - if (!bytes_written) + + 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){ return false; + } #elif defined(ESP8266) if (!i2s_write_sample_nb(dsBuff[0])) return false; // No room at the inn // At this point we've sent in first of possibly 8 32-bits, need to send diff --git a/lib/lib_audio/ESP8266Audio/src/AudioOutputSPDIF.cpp b/lib/lib_audio/ESP8266Audio/src/AudioOutputSPDIF.cpp index 53483d4ac..6e1cf1978 100644 --- a/lib/lib_audio/ESP8266Audio/src/AudioOutputSPDIF.cpp +++ b/lib/lib_audio/ESP8266Audio/src/AudioOutputSPDIF.cpp @@ -3,7 +3,7 @@ S/PDIF output via I2S - Needs transciever from CMOS level to either optical or coaxial interface + Needs transceiver from CMOS level to either optical or coaxial interface See: https://www.epanorama.net/documents/audio/spdif.html Original idea and sources: @@ -94,7 +94,11 @@ AudioOutputSPDIF::AudioOutputSPDIF(int dout_pin, int port, int dma_buf_count) .sample_rate = 88200, // 2 x sampling_rate .bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT, // 32bit words .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, // Right than left - .communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB), +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) + .communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_STAND_I2S), +#else + .communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB), +#endif .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 @@ -265,7 +269,7 @@ bool AudioOutputSPDIF::ConsumeSample(int16_t sample[2]) #if defined(ESP32) // Assume DMA buffers are multiples of 16 bytes. Either we write all bytes or none. - uint32_t bytes_written; + size_t bytes_written; esp_err_t ret = i2s_write((i2s_port_t)portNo, (const char*)&buf, 8 * channels, &bytes_written, 0); // If we didn't write all bytes, return false early and do not increment frame_num if ((ret != ESP_OK) || (bytes_written != (8 * channels))) return false; diff --git a/lib/lib_audio/ESP8266Audio/src/AudioOutputSPDIF.h b/lib/lib_audio/ESP8266Audio/src/AudioOutputSPDIF.h index 5da160b3d..7cb194dbc 100644 --- a/lib/lib_audio/ESP8266Audio/src/AudioOutputSPDIF.h +++ b/lib/lib_audio/ESP8266Audio/src/AudioOutputSPDIF.h @@ -3,7 +3,7 @@ S/PDIF output via I2S - Needs transciever from CMOS level to either optical or coaxial interface + Needs transceiver from CMOS level to either optical or coaxial interface See: https://www.epanorama.net/documents/audio/spdif.html Original idea and sources: diff --git a/lib/lib_audio/ESP8266Audio/src/AudioOutputSTDIO.cpp b/lib/lib_audio/ESP8266Audio/src/AudioOutputSTDIO.cpp index 33bbd34f8..f9032bb12 100644 --- a/lib/lib_audio/ESP8266Audio/src/AudioOutputSTDIO.cpp +++ b/lib/lib_audio/ESP8266Audio/src/AudioOutputSTDIO.cpp @@ -54,6 +54,11 @@ bool AudioOutputSTDIO::begin() bool AudioOutputSTDIO::ConsumeSample(int16_t sample[2]) { + static int avail = 100; + if (!(--avail)) { + avail = 100; + return false; + } for (int i=0; i. */ -#ifdef ESP32 +#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 #include "AudioOutputULP.h" #include diff --git a/lib/lib_audio/ESP8266Audio/src/driver/SinglePinI2SDriver.cpp b/lib/lib_audio/ESP8266Audio/src/driver/SinglePinI2SDriver.cpp index 3d08efaf0..c2d2280c0 100644 --- a/lib/lib_audio/ESP8266Audio/src/driver/SinglePinI2SDriver.cpp +++ b/lib/lib_audio/ESP8266Audio/src/driver/SinglePinI2SDriver.cpp @@ -3,7 +3,7 @@ ESP8266Audio I2S Minimal driver Most of this code is taken and reworked from ESP8266 Arduino core, - which itsef is reworked from Espessif's I2S examples. + which itself is reworked from Espessif's I2S examples. Original code is licensed under LGPL 2.1 or above Reasons for rewrite: @@ -196,7 +196,7 @@ void SinglePinI2SDriver::setDividers(uint8_t div1, uint8_t div2) // Ensure dividers fit in bit fields div1 &= I2SBDM; div2 &= I2SCDM; - // trans master(active low), recv master(active_low), !bits mod(==16 bits/chanel), clear clock dividers + // trans master(active low), recv master(active_low), !bits mod(==16 bits/channel), clear clock dividers I2SC &= ~(I2STSM | I2SRSM | (I2SBMM << I2SBM) | (I2SBDM << I2SBD) | (I2SCDM << I2SCD)); // I2SRF = Send/recv right channel first // I2SMR = MSB recv/xmit first @@ -249,7 +249,7 @@ void SinglePinI2SDriver::startI2S() I2SFC |= I2SDE; // Enable DMA // I2STXCMM, I2SRXCMM=0 => Dual channel mode, RX/TX CHAN_MOD=0 I2SCC &= ~((I2STXCMM << I2STXCM) | (I2SRXCMM << I2SRXCM)); - // Set dividers to something resonable + // Set dividers to something reasonable currentRate = 0; setRate(44100); // Start I2S peripheral @@ -280,4 +280,4 @@ int SinglePinI2SDriver::getUnderflowCount() // Global instance SinglePinI2SDriver I2SDriver; -#endif // defined(ESP8266) \ No newline at end of file +#endif // defined(ESP8266) diff --git a/lib/lib_audio/ESP8266Audio/src/libflac/stream_decoder.c b/lib/lib_audio/ESP8266Audio/src/libflac/stream_decoder.c index ec172fe8d..20ae399f5 100644 --- a/lib/lib_audio/ESP8266Audio/src/libflac/stream_decoder.c +++ b/lib/lib_audio/ESP8266Audio/src/libflac/stream_decoder.c @@ -2199,14 +2199,14 @@ FLAC__bool read_frame_header_(FLAC__StreamDecoder *decoder) * Three kinds of things can go wrong when reading the frame header: * 1) We may have sync'ed incorrectly and not landed on a frame header. * If we don't find a sync code, it can end up looking like we read - * a valid but unparseable header, until getting to the frame header + * a valid but unparsable header, until getting to the frame header * CRC. Even then we could get a false positive on the CRC. - * 2) We may have sync'ed correctly but on an unparseable frame (from a + * 2) We may have sync'ed correctly but on an unparsable frame (from a * future encoder). - * 3) We may be on a damaged frame which appears valid but unparseable. + * 3) We may be on a damaged frame which appears valid but unparsable. * * For all these reasons, we try and read a complete frame header as - * long as it seems valid, even if unparseable, up until the frame + * long as it seems valid, even if unparsable, up until the frame * header CRC. */ @@ -2839,7 +2839,7 @@ FLAC__bool read_callback_(FLAC__byte buffer[], size_t *bytes, void *client_data) * FLAC__STREAM_DECODER_UNPARSEABLE_STREAM and increment its * unparseable_frame_count. But there is a remote possibility * that it is properly synced at such a "future-codec frame", - * so to make sure, we wait to see many "unparseable" errors in + * so to make sure, we wait to see many "unparsable" errors in * a row before bailing out. */ if(decoder->private_->is_seeking && decoder->private_->unparseable_frame_count > 20) { @@ -3146,7 +3146,7 @@ FLAC__bool seek_to_absolute_sample_(FLAC__StreamDecoder *decoder, FLAC__uint64 s return false; } /* Now we need to get a frame. First we need to reset our - * unparseable_frame_count; if we get too many unparseable + * unparseable_frame_count; if we get too many unparsable * frames in a row, the read callback will return * FLAC__STREAM_DECODER_READ_STATUS_ABORT, causing * FLAC__stream_decoder_process_single() to return false. diff --git a/lib/lib_audio/ESP8266Audio/src/libhelix-aac/assembly.h b/lib/lib_audio/ESP8266Audio/src/libhelix-aac/assembly.h index 595a8fc97..0c17f0c44 100644 --- a/lib/lib_audio/ESP8266Audio/src/libhelix-aac/assembly.h +++ b/lib/lib_audio/ESP8266Audio/src/libhelix-aac/assembly.h @@ -558,7 +558,7 @@ static __inline int CLZ(int x) typedef union _U64 { Word64 w64; struct { -#ifdef __XTENSA__ +#if defined(__XTENSA__) || defined (__riscv) unsigned int lo32; signed int hi32; #else diff --git a/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/RPSL.txt b/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/RPSL.txt index d040a4520..94b44586d 100644 --- a/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/RPSL.txt +++ b/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/RPSL.txt @@ -201,7 +201,7 @@ and 3, above. 4.2 Compatible Source Licenses. Software modules that have been independently developed without any use of Covered Code and which contain no portion of the Covered Code, Modifications or other Derivative Works, but are used or combined -in any way wtih the Covered Code or any Derivative Work to form a larger +in any way with the Covered Code or any Derivative Work to form a larger Derivative Work, are exempt from the conditions described in Section 4.1 but only to the extent that: the software module, including any software that is linked to, integrated with, or part of the same applications as, the software diff --git a/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/assembly.h b/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/assembly.h index b9e46c529..5ad0f30b8 100644 --- a/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/assembly.h +++ b/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/assembly.h @@ -40,7 +40,7 @@ * * assembly.h - assembly language functions and prototypes for supported platforms * - * - inline rountines with access to 64-bit multiply results + * - inline routines with access to 64-bit multiply results * - x86 (_WIN32) and ARM (ARM_ADS, _WIN32_WCE) versions included * - some inline functions are mix of asm and C for speed * - some functions are in native asm files, so only the prototype is given here @@ -241,7 +241,7 @@ static __inline int MULSHIFT32(int x, int y) static __inline int FASTABS(int x) { - int t=0; /*Really is not necessary to initialiaze only to avoid warning*/ + int t=0; /*Really is not necessary to initialize only to avoid warning*/ __asm { eor t, x, x, asr #31 diff --git a/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/scalfact.c b/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/scalfact.c index 4937e4530..d274b3615 100644 --- a/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/scalfact.c +++ b/lib/lib_audio/ESP8266Audio/src/libhelix-mp3/scalfact.c @@ -74,7 +74,7 @@ static const char SFLenTab[16][2] = { * Return: none * * Notes: set order of short blocks to s[band][window] instead of s[window][band] - * so that we index through consectutive memory locations when unpacking + * so that we index through consecutive memory locations when unpacking * (make sure dequantizer follows same convention) * Illegal Intensity Position = 7 (always) for MPEG1 scale factors **************************************************************************************/ diff --git a/lib/lib_audio/ESP8266Audio/src/libogg/README.md b/lib/lib_audio/ESP8266Audio/src/libogg/README.md index 63545e288..c3be01460 100644 --- a/lib/lib_audio/ESP8266Audio/src/libogg/README.md +++ b/lib/lib_audio/ESP8266Audio/src/libogg/README.md @@ -7,7 +7,7 @@ Ogg project codecs use the Ogg bitstream format to arrange the raw, compressed bitstream into a more robust, useful form. For example, the Ogg bitstream makes seeking, time stamping and error recovery -possible, as well as mixing several sepearate, concurrent media +possible, as well as mixing several separate, concurrent media streams into a single physical bitstream. ## What's here ## @@ -18,7 +18,7 @@ use with Ogg bitstreams. Directory: -- `src` The source for libogg, a BSD-license inplementation of the public domain Ogg bitstream format +- `src` The source for libogg, a BSD-license implementation of the public domain Ogg bitstream format - `include` Library API headers diff --git a/lib/lib_audio/ESP8266Audio/src/libtinysoundfont/README.ESP8266 b/lib/lib_audio/ESP8266Audio/src/libtinysoundfont/README.ESP8266 index e88104dfc..1009f36f6 100644 --- a/lib/lib_audio/ESP8266Audio/src/libtinysoundfont/README.ESP8266 +++ b/lib/lib_audio/ESP8266Audio/src/libtinysoundfont/README.ESP8266 @@ -28,7 +28,7 @@ Even with the caching, it was found that SPIFFS, while having great functionality, was horrbly slow. So I wrote a new "faster" ROM filesystem called, surprisingly, FastROMFilesystem. https://github.com/earlephilhower/ESP8266FastROMFS -If you are getting choppy playback, try this new filesytem or using a SD +If you are getting choppy playback, try this new filesystem or using a SD card (not tested by myself, but it'd be hard top be slower than SPIFFS). Simply going from SPIFFS to FastROMFilesystem took my testing of FURELISE.MID and 1MGM.SF2 from 0.5x realtime to 2.5x (i.e. from unusable diff --git a/lib/lib_audio/ESP8266Audio/src/libtinysoundfont/tsf.h b/lib/lib_audio/ESP8266Audio/src/libtinysoundfont/tsf.h index e786d1662..45d7b97a5 100644 --- a/lib/lib_audio/ESP8266Audio/src/libtinysoundfont/tsf.h +++ b/lib/lib_audio/ESP8266Audio/src/libtinysoundfont/tsf.h @@ -104,7 +104,7 @@ TSFDEF tsf* tsf_load(struct tsf_stream* stream); // Free the memory related to this tsf instance TSFDEF void tsf_close(tsf* f); -// Stop all playing notes immediatly and reset all channel parameters +// Stop all playing notes immediately and reset all channel parameters TSFDEF void tsf_reset(tsf* f); // Returns the preset index from a bank and preset number, or -1 if it does not exist in the loaded SoundFont @@ -202,7 +202,7 @@ TSFDEF void tsf_channel_set_tuning(tsf* f, int channel, float tuning); TSFDEF void tsf_channel_note_on(tsf* f, int channel, int key, float vel); TSFDEF void tsf_channel_note_off(tsf* f, int channel, int key); TSFDEF void tsf_channel_note_off_all(tsf* f, int channel); //end with sustain and release -TSFDEF void tsf_channel_sounds_off_all(tsf* f, int channel); //end immediatly +TSFDEF void tsf_channel_sounds_off_all(tsf* f, int channel); //end immediately // Apply a MIDI control change to the channel (not all controllers are supported!) TSFDEF void tsf_channel_midi_control(tsf* f, int channel, int controller, int control_value); diff --git a/lib/lib_audio/ESP8266Audio/src/opusfile/opusfile.h b/lib/lib_audio/ESP8266Audio/src/opusfile/opusfile.h index 7a6457240..11cc07a16 100644 --- a/lib/lib_audio/ESP8266Audio/src/opusfile/opusfile.h +++ b/lib/lib_audio/ESP8266Audio/src/opusfile/opusfile.h @@ -729,7 +729,7 @@ struct OpusServerInfo{ /**The software used by the origin server (Server). This is NULL if there was no Server header.*/ char *server; - /**The media type of the entity sent to the recepient (Content-Type). + /**The media type of the entity sent to the recipient (Content-Type). This is NULL if there was no Content-Type header.*/ char *content_type; @@ -1436,7 +1436,7 @@ void op_free(OggOpusFile *_of); Some of these functions may be used successfully on the partially open streams returned by op_test_callbacks() or one of the associated convenience functions. - Their documention will indicate so explicitly.*/ + Their documentation will indicate so explicitly.*/ /*@{*/ /**Returns whether or not the stream being read is seekable. diff --git a/lib/lib_audio/ESP8266Audio/tests/common.sh b/lib/lib_audio/ESP8266Audio/tests/common.sh index cabad512f..25c05cd66 100755 --- a/lib/lib_audio/ESP8266Audio/tests/common.sh +++ b/lib/lib_audio/ESP8266Audio/tests/common.sh @@ -58,7 +58,7 @@ function build_sketches() local sketchdirname=$(basename $sketchdir) local sketchname=$(basename $sketch) if [[ "${sketchdirname}.ino" != "$sketchname" ]]; then - echo "Skipping $sketch, beacause it is not the main sketch file"; + echo "Skipping $sketch, because it is not the main sketch file"; continue fi; if [[ -f "$sketchdir/.test.skip" ]]; then diff --git a/lib/lib_audio/ESP8266Audio/tests/host/Makefile b/lib/lib_audio/ESP8266Audio/tests/host/Makefile index 25156dbcd..15eee60e6 100644 --- a/lib/lib_audio/ESP8266Audio/tests/host/Makefile +++ b/lib/lib_audio/ESP8266Audio/tests/host/Makefile @@ -83,7 +83,7 @@ CPPOPTS=-g -Wunused-parameter -Wall -std=c++11 -m32 -Wstack-usage=300 -include A .phony: all -all: mp3 aac wav midi opus flac +all: mp3 aac wav midi opus flac mod mp3: FORCE rm -f *.o @@ -106,6 +106,12 @@ flac: FORCE rm -f *.o echo valgrind --leak-check=full --track-origins=yes -v --error-limit=no --show-leak-kinds=all ./flac +mod: FORCE + rm -f *.o + g++ $(CPPOPTS) -o mod mod.cpp Serial.cpp ../../src/AudioFileSourcePROGMEM.cpp ../../src/AudioOutputSTDIO.cpp ../../src/AudioGeneratorMOD.cpp ../../src/AudioLogger.cpp -I ../../src/ -I. + rm -f *.o + echo valgrind --leak-check=full --track-origins=yes -v --error-limit=no --show-leak-kinds=all ./mod + wav: FORCE rm -f *.o g++ $(CPPOPTS) -o wav wav.cpp Serial.cpp ../../src/AudioFileSourceSTDIO.cpp ../../src/AudioOutputSTDIO.cpp ../../src/AudioGeneratorWAV.cpp ../../src/AudioLogger.cpp -I ../../src/ -I. @@ -128,6 +134,6 @@ opus: FORCE echo valgrind --leak-check=full --track-origins=yes -v --error-limit=no --show-leak-kinds=all ./opus clean: - rm -f mp3 aac wav midi opus flac *.o + rm -f mp3 aac wav midi opus flac mod *.o FORCE: diff --git a/lib/lib_audio/ESP8266Audio/tests/host/mod.cpp b/lib/lib_audio/ESP8266Audio/tests/host/mod.cpp new file mode 100644 index 000000000..18da2ce35 --- /dev/null +++ b/lib/lib_audio/ESP8266Audio/tests/host/mod.cpp @@ -0,0 +1,26 @@ +#include +#include "AudioFileSourcePROGMEM.h" +#include "AudioOutputSTDIO.h" +#include "AudioGeneratorMOD.h" + +#include "../../examples/PlayMODFromPROGMEMToDAC/enigma.h" + +int main(int argc, char **argv) +{ + (void) argc; + (void) argv; + + AudioFileSourcePROGMEM *file = new AudioFileSourcePROGMEM(enigma_mod, sizeof(enigma_mod)); + AudioOutputSTDIO *out = new AudioOutputSTDIO(); + out->SetFilename("mod.wav"); + AudioGeneratorMOD *mod = new AudioGeneratorMOD(); + + mod->begin(file, out); + // The MOD plays forever, so only run for ~30 seconds worth + for (int i=0; i<10000; i++) mod->loop(); + mod->stop(); + + delete out; + delete mod; + delete file; +} diff --git a/lib/lib_audio/ESP8266SAM/README.md b/lib/lib_audio/ESP8266SAM/README.md index 6fb215564..694086db2 100644 --- a/lib/lib_audio/ESP8266SAM/README.md +++ b/lib/lib_audio/ESP8266SAM/README.md @@ -23,6 +23,10 @@ Output is fixed at 22050Hz due to some hardcoded delays to help match C64 intern The voice is formant generated and can be modified by setting things such as speed, pitch, mouth and throat configuration, and even sending in phonetic codes instead of English text. See @s-macke's repository for more information. +## Cool uses of SAM +Jan Derogee has used ESP8266SAM to build a complete VIC-20 compatible speech synthesis cartridge that works with BASIC applications. It also has a great background on early speech synthesis and a neat construction and demo video. Check it out at https://janderogee.com/projects/SerialSpeechSynthesisSAM/SerialSpeechSynthesisSAM.htm + + ## License While the ESP8266 wrapper is my own, the SAM software is a reverse-engineered version of a software published more than 34 years ago by "Don't ask Software". diff --git a/lib/lib_audio/ESP8266SAM/examples/SpeakNoDac/SpeakNoDac.ino b/lib/lib_audio/ESP8266SAM/examples/SpeakNoDac/SpeakNoDac.ino new file mode 100644 index 000000000..6951fe855 --- /dev/null +++ b/lib/lib_audio/ESP8266SAM/examples/SpeakNoDac/SpeakNoDac.ino @@ -0,0 +1,20 @@ +#include +#include +#include "AudioOutputI2SNoDAC.h" + +AudioOutputI2SNoDAC *out = NULL; + +void setup() +{ + out = new AudioOutputI2SNoDAC(); + out->begin(); +} + +void loop() +{ + ESP8266SAM *sam = new ESP8266SAM; + sam->Say(out, "Can you hear me now?"); + delay(500); + sam->Say(out, "I can't hear you!"); + delete sam; +} diff --git a/lib/lib_audio/ESP8266SAM/examples/remoteSAM/remoteSAM.ino b/lib/lib_audio/ESP8266SAM/examples/remoteSAM/remoteSAM.ino new file mode 100644 index 000000000..d6a82991e --- /dev/null +++ b/lib/lib_audio/ESP8266SAM/examples/remoteSAM/remoteSAM.ino @@ -0,0 +1,129 @@ +// In a webbrowser go to http://sam.local/say/{message} to make it speak +// ex: http://sam.local/say/hello world + +#include + +#if !defined(ESP8266) +#error This example is only for the ESP8266 +#endif + +#include +#include "AudioOutputI2SNoDAC.h" + +#include +#include +#include //Library for SSDP (Show ESP in Network on Windows) +#include //Library for WebServer +#include +#include + +AudioOutputI2SNoDAC *out = NULL; + +ESP8266WebServer server(80); //Web Server on port 80 +WiFiManager wifiManager; +const char* NAME = "SAM"; + +void setup() +{ + Serial.begin(115200); + out = new AudioOutputI2SNoDAC(); + out->begin(); + + wifiManager.autoConnect(NAME); + + MDNS.begin(NAME); + MDNS.addService("http", "tcp", 80); + NBNS.begin(NAME); + + server.on(UriBraces("/say/{}"), []() { + String message_encoded = server.pathArg(0); + String message_decoded = urldecode(message_encoded); + const char* message = message_decoded.c_str(); + + Serial.println(message_encoded); + Serial.println(message_decoded); + Serial.println(message); + + ESP8266SAM *sam = new ESP8266SAM; + sam->Say(out, message); + delete sam; + server.send(200, "text/plain", "OK"); + }); + + server.on("/description.xml", HTTP_GET, []() { + SSDP.schema(server.client()); + }); + server.begin(); + ssdp(); +} + +void ssdp() { + //Simple Service Discovery Protocol : Display ESP in Windows Network Tab + SSDP.setSchemaURL("description.xml"); + SSDP.setHTTPPort(80); + SSDP.setName(NAME); + SSDP.setDeviceType("upnp: rootdevice"); + SSDP.setSerialNumber("000000000001"); + SSDP.setURL("/say/connected"); + SSDP.setModelName("ESP8266SAM"); + SSDP.setModelNumber("0000000000001"); + SSDP.setModelURL("https://github.com/earlephilhower/ESP8266SAM"); + SSDP.setManufacturer("earlephilhower"); + SSDP.setManufacturerURL("https://github.com/earlephilhower/"); + SSDP.begin(); +} + +void loop() { + server.handleClient(); +} + +char* string2char(String command) { + if (command.length() != 0) { + char *p = const_cast(command.c_str()); + return p; + } else { + return ""; + } +} + +unsigned char h2int(char c) { + if (c >= '0' && c <= '9') { + return ((unsigned char)c - '0'); + } + if (c >= 'a' && c <= 'f') { + return ((unsigned char)c - 'a' + 10); + } + if (c >= 'A' && c <= 'F') { + return ((unsigned char)c - 'A' + 10); + } + return (0); +} + +String urldecode(String str) +{ + + String encodedString = ""; + char c; + char code0; + char code1; + for (int i = 0; i < str.length(); i++) { + c = str.charAt(i); + if (c == '+') { + encodedString += ' '; + } else if (c == '%') { + i++; + code0 = str.charAt(i); + i++; + code1 = str.charAt(i); + c = (h2int(code0) << 4) | h2int(code1); + encodedString += c; + } else { + + encodedString += c; + } + + yield(); + } + + return encodedString; +} diff --git a/lib/lib_audio/ESP8266SAM/library.json b/lib/lib_audio/ESP8266SAM/library.json index af66aee97..d03ac694c 100644 --- a/lib/lib_audio/ESP8266SAM/library.json +++ b/lib/lib_audio/ESP8266SAM/library.json @@ -1,7 +1,7 @@ { "name": "ESP8266SAM", - "description": "Speech synthesizer SAM ported to ESP8266/ESP32", - "keywords": "ESP8266, ESP32, Speecn Synthesis, SAM", + "description": "Speech synthesizer SAM ported to ESP8266/ESP32/RP2040", + "keywords": "ESP8266, ESP32, RP2040, Speecn Synthesis, SAM", "authors": [ { "name": "Earle F. Philhower, III", @@ -14,10 +14,9 @@ "type": "git", "url": "https://github.com/earlephilhower/ESP8266SAM" }, - "version": "1.0", + "version": "1.0.1", "homepage": "https://github.com/earlephilhower/ESP8266SAM", "frameworks": "Arduino", - "platforms": ["espressif8266", "espressif32"], "examples": [ "examples/*/*.ino" ] diff --git a/lib/lib_audio/ESP8266SAM/library.properties b/lib/lib_audio/ESP8266SAM/library.properties index ed295ef12..f4624783c 100644 --- a/lib/lib_audio/ESP8266SAM/library.properties +++ b/lib/lib_audio/ESP8266SAM/library.properties @@ -1,9 +1,9 @@ name=ESP8266SAM -version=1.0 +version=1.0.1 author=Earle F. Philhower, III maintainer=Earle F. Philhower, III -sentence=Speech synthesis on the ESP8266 and ESP32 -paragraph=Speech synthesis program SAM ported to ESP8266/ESP32 and ESP8266Audio +sentence=Speech synthesis on the ESP8266, ESP32, and RP2040 +paragraph=Speech synthesis program SAM ported to ESP8266/ESP32/RP2040 and ESP8266Audio category=Signal Input/Output url=https://github.com/earlephilhower/ESP8266SAM -architectures=esp8266,esp32 +architectures=esp8266,esp32,rp2040 diff --git a/lib/lib_audio/ESP8266SAM/src/ESP8266SAM.h b/lib/lib_audio/ESP8266SAM/src/ESP8266SAM.h index d947c72f0..526f41b91 100644 --- a/lib/lib_audio/ESP8266SAM/src/ESP8266SAM.h +++ b/lib/lib_audio/ESP8266SAM/src/ESP8266SAM.h @@ -1,7 +1,7 @@ /* ESP8266SAM Port of SAM to the ESP8266 - + Copyright (C) 2017 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 @@ -34,7 +34,7 @@ public: speed = 0; output = NULL; }; - + ~ESP8266SAM() { } @@ -70,3 +70,4 @@ private: }; #endif + diff --git a/lib/lib_audio/ESP8266SAM/src/ReciterTabs.h b/lib/lib_audio/ESP8266SAM/src/ReciterTabs.h index c89636e4d..3f152cc6a 100644 --- a/lib/lib_audio/ESP8266SAM/src/ReciterTabs.h +++ b/lib/lib_audio/ESP8266SAM/src/ReciterTabs.h @@ -2,8 +2,8 @@ #define RECITERTABS_H #include -#include "samdebug.h" -#if sam_debug +#include "esp8266sam_debug.h" +#if DEBUG_ESP8266SAM_LIB #define PROGMEM #endif diff --git a/lib/lib_audio/ESP8266SAM/src/RenderTabs.h b/lib/lib_audio/ESP8266SAM/src/RenderTabs.h index a98e93bc7..c492fb9c5 100644 --- a/lib/lib_audio/ESP8266SAM/src/RenderTabs.h +++ b/lib/lib_audio/ESP8266SAM/src/RenderTabs.h @@ -2,8 +2,8 @@ #define RENDERTABS_H #include -#include "samdebug.h" -#if sam_debug +#include "esp8266sam_debug.h" +#if DEBUG_ESP8266SAM_LIB #define PROGMEM #endif @@ -196,7 +196,7 @@ const unsigned char ampl3data[] PROGMEM = //tab42240 -const signed char sinus[256] PROGMEM = {0,3,6,9,12,16,19,22,25,28,31,34,37,40,43,46,49,51,54,57,60,63,65,68,71,73,76,78,81,83,85,88,90,92,94,96,98,100,102,104,106,107,109,111,112,113,115,116,117,118,120,121,122,122,123,124,125,125,126,126,126,127,127,127,127,127,127,127,126,126,126,125,125,124,123,122,122,121,120,118,117,116,115,113,112,111,109,107,106,104,102,100,98,96,94,92,90,88,85,83,81,78,76,73,71,68,65,63,60,57,54,51,49,46,43,40,37,34,31,28,25,22,19,16,12,9,6,3,0,-3,-6,-9,-12,-16,-19,-22,-25,-28,-31,-34,-37,-40,-43,-46,-49,-51,-54,-57,-60,-63,-65,-68,-71,-73,-76,-78,-81,-83,-85,-88,-90,-92,-94,-96,-98,-100,-102,-104,-106,-107,-109,-111,-112,-113,-115,-116,-117,-118,-120,-121,-122,-122,-123,-124,-125,-125,-126,-126,-126,-127,-127,-127,-127,-127,-127,-127,-126,-126,-126,-125,-125,-124,-123,-122,-122,-121,-120,-118,-117,-116,-115,-113,-112,-111,-109,-107,-106,-104,-102,-100,-98,-96,-94,-92,-90,-88,-85,-83,-81,-78,-76,-73,-71,-68,-65,-63,-60,-57,-54,-51,-49,-46,-43,-40,-37,-34,-31,-28,-25,-22,-19,-16,-12,-9,-6,-3}; +const signed char sinus[256] PROGMEM = {0,3,6,9,12,16,19,22,25,28,31,34,37,40,43,46,49,51,54,57,60,63,65,68,71,73,76,78,81,83,85,88,90,92,94,96,98,100,102,104,106,107,109,111,112,113,115,116,117,118,120,121,122,122,123,124,125,125,126,126,126,127,127,127,127,127,127,127,126,126,126,125,125,124,123,122,122,121,120,118,117,116,115,113,112,111,109,107,106,104,102,100,98,96,94,92,90,88,85,83,81,78,76,73,71,68,65,63,60,57,54,51,49,46,43,40,37,34,31,28,25,22,19,16,12,9,6,3,0,-3,-6,-9,-12,-16,-19,-22,-25,-28,-31,-34,-37,-40,-43,-46,-49,-51,-54,-57,-60,-63,-65,-68,-71,-73,-76,-78,-81,-83,-85,-88,-90,-92,-94,-96,-98,-100,-102,-104,-106,-107,-109,-111,-112,-113,-115,-116,-117,-118,-120,-121,-122,-122,-123,-124,-125,-125,-126,-126,-126,-127,-127,-127,-127,-127,-127,-127,-126,-126,-126,-125,-125,-124,-123,-122,-122,-121,-120,-118,-117,-116,-115,-113,-112,-111,-109,-107,-106,-104,-102,-100,-98,-96,-94,-92,-90,-88,-85,-83,-81,-78,-76,-73,-71,-68,-65,-63,-60,-57,-54,-51,-49,-46,-43,-40,-37,-34,-31,-28,-25,-22,-19,-16,-12,-9,-6,-3}; //tab42496 const unsigned char rectangle[] PROGMEM = diff --git a/lib/lib_audio/ESP8266SAM/src/SamTabs.h b/lib/lib_audio/ESP8266SAM/src/SamTabs.h index 4574746e7..933f95b0e 100644 --- a/lib/lib_audio/ESP8266SAM/src/SamTabs.h +++ b/lib/lib_audio/ESP8266SAM/src/SamTabs.h @@ -2,8 +2,8 @@ #define SAMTABS_H #include -#include "samdebug.h" -#if sam_debug +#include "esp8266sam_debug.h" +#if DEBUG_ESP8266SAM_LIB #define PROGMEM #endif diff --git a/lib/lib_audio/ESP8266SAM/src/samdebug.c b/lib/lib_audio/ESP8266SAM/src/esp8266sam_debug.c similarity index 100% rename from lib/lib_audio/ESP8266SAM/src/samdebug.c rename to lib/lib_audio/ESP8266SAM/src/esp8266sam_debug.c diff --git a/lib/lib_audio/ESP8266SAM/src/samdebug.h b/lib/lib_audio/ESP8266SAM/src/esp8266sam_debug.h similarity index 79% rename from lib/lib_audio/ESP8266SAM/src/samdebug.h rename to lib/lib_audio/ESP8266SAM/src/esp8266sam_debug.h index 5f862a0e6..de2a2f840 100644 --- a/lib/lib_audio/ESP8266SAM/src/samdebug.h +++ b/lib/lib_audio/ESP8266SAM/src/esp8266sam_debug.h @@ -1,5 +1,5 @@ -#ifndef DEBUG_H -#define DEBUG_H +#ifndef ESP8266SAM_DEBUG_H +#define ESP8266SAM_DEBUG_H void PrintPhonemes(unsigned char *phonemeindex, unsigned char *phonemeLength, unsigned char *stress); void PrintOutput( @@ -14,6 +14,6 @@ void PrintOutput( void PrintRule(int offset); -#define sam_debug 0 +#define DEBUG_ESP8266SAM_LIB 0 #endif diff --git a/lib/lib_audio/ESP8266SAM/src/reciter.c b/lib/lib_audio/ESP8266SAM/src/reciter.c index 3845609c3..f949ca579 100644 --- a/lib/lib_audio/ESP8266SAM/src/reciter.c +++ b/lib/lib_audio/ESP8266SAM/src/reciter.c @@ -2,7 +2,7 @@ #include #include "reciter.h" #include "ReciterTabs.h" -#include "samdebug.h" +#include "esp8266sam_debug.h" #include "SamData.h" unsigned char A, X, Y; @@ -527,7 +527,7 @@ pos37455: Y = mem64; mem61 = mem60; - if (sam_debug) + if (DEBUG_ESP8266SAM_LIB) PrintRule(mem62); pos37461: diff --git a/lib/lib_audio/ESP8266SAM/src/render.c b/lib/lib_audio/ESP8266SAM/src/render.c index f73c848a4..4cbabb190 100644 --- a/lib/lib_audio/ESP8266SAM/src/render.c +++ b/lib/lib_audio/ESP8266SAM/src/render.c @@ -5,8 +5,7 @@ #include "render.h" #include "RenderTabs.h" -#include "samdebug.h" -//extern int debug; +#include "esp8266sam_debug.h" #include #include "SamData.h" @@ -445,7 +444,7 @@ do mem44++; } while(mem44 != 0); yield(); -if (sam_debug) +if (DEBUG_ESP8266SAM_LIB) { PrintOutput(sampledConsonantFlag, frequency1, frequency2, frequency3, amplitude1, amplitude2, amplitude3, pitches); } @@ -786,7 +785,7 @@ if (sam_debug) X = A; mem38 = A - (A>>2); // 3/4*A ??? yield(); -if (sam_debug) +if (DEBUG_ESP8266SAM_LIB) { PrintOutput(sampledConsonantFlag, frequency1, frequency2, frequency3, amplitude1, amplitude2, amplitude3, pitches); } diff --git a/lib/lib_audio/ESP8266SAM/src/sam.c b/lib/lib_audio/ESP8266SAM/src/sam.c index 5dba52fda..c20d8dd2a 100644 --- a/lib/lib_audio/ESP8266SAM/src/sam.c +++ b/lib/lib_audio/ESP8266SAM/src/sam.c @@ -2,7 +2,7 @@ #include // strlen() //#include #include // define NULL -#include "samdebug.h" +#include "esp8266sam_debug.h" #include "sam.h" #include "render.h" #include "SamTabs.h" @@ -15,8 +15,6 @@ static unsigned char mouth = 128; static unsigned char throat = 128; int singmode = 0; -//extern int debug; - unsigned char mem39; unsigned char mem44; unsigned char mem47; @@ -146,7 +144,7 @@ int SAMMain( void (*cb)(void *, unsigned char), void *cbd ) phonemeindex[255] = 32; //to prevent buffer overflow if (!Parser1()) return 0; - if (sam_debug) + if (DEBUG_ESP8266SAM_LIB) PrintPhonemes(phonemeindex, phonemeLength, stress); Parser2(); CopyStress(); @@ -168,7 +166,7 @@ int SAMMain( void (*cb)(void *, unsigned char), void *cbd ) InsertBreath(); //mem[40158] = 255; - if (sam_debug) + if (DEBUG_ESP8266SAM_LIB) { PrintPhonemes(phonemeindex, phonemeLength, stress); } @@ -645,7 +643,7 @@ void Code41240() //void Code41397() void Parser2() { - if (sam_debug) printf("Parser2\n"); + if (DEBUG_ESP8266SAM_LIB) printf("Parser2\n"); unsigned char pos = 0; //mem66; unsigned char mem58 = 0; @@ -659,7 +657,7 @@ void Parser2() A = phonemeindex[pos]; // DEBUG: Print phoneme and index - if (sam_debug && A != 255) printf("%d: %c%c\n", X, signInputTable1[A], signInputTable2[A]); + if (DEBUG_ESP8266SAM_LIB && A != 255) printf("%d: %c%c\n", X, signInputTable1[A], signInputTable2[A]); // Is phoneme pause? if (A == 0) @@ -695,8 +693,8 @@ void Parser2() //pos41443: // Insert at WX or YX following, copying the stress - if (sam_debug) if (A==20) printf("RULE: insert WX following diphtong NOT ending in IY sound\n"); - if (sam_debug) if (A==21) printf("RULE: insert YX following diphtong ending in IY sound\n"); + if (DEBUG_ESP8266SAM_LIB) if (A==20) printf("RULE: insert WX following diphtong NOT ending in IY sound\n"); + if (DEBUG_ESP8266SAM_LIB) if (A==21) printf("RULE: insert YX following diphtong ending in IY sound\n"); Insert(pos+1, A, mem59, mem58); X = pos; // Jump to ??? @@ -716,7 +714,7 @@ pos41457: if (A != 78) goto pos41487; // 'UL' A = 24; // 'L' //change 'UL' to 'AX L' - if (sam_debug) printf("RULE: UL -> AX L\n"); + if (DEBUG_ESP8266SAM_LIB) printf("RULE: UL -> AX L\n"); pos41466: // Get current phoneme stress @@ -740,7 +738,7 @@ pos41487: if (A != 79) goto pos41495; // 'UM' // Jump up to branch - replaces current phoneme with AX and continues A = 27; // 'M' //change 'UM' to 'AX M' - if (sam_debug) printf("RULE: UM -> AX M\n"); + if (DEBUG_ESP8266SAM_LIB) printf("RULE: UM -> AX M\n"); goto pos41466; pos41495: @@ -754,7 +752,7 @@ pos41495: // Jump up to branch - replaces current phoneme with AX and continues A = 28; // 'N' //change UN to 'AX N' - if (sam_debug) printf("RULE: UN -> AX N\n"); + if (DEBUG_ESP8266SAM_LIB) printf("RULE: UN -> AX N\n"); goto pos41466; pos41503: @@ -802,7 +800,7 @@ pos41503: if (A != 0) { // Insert a glottal stop and move forward - if (sam_debug) printf("RULE: Insert glottal stop between two stressed vowels with space between them\n"); + if (DEBUG_ESP8266SAM_LIB) printf("RULE: Insert glottal stop between two stressed vowels with space between them\n"); // 31 = 'Q' Insert(X, 31, mem59, 0); pos++; @@ -831,7 +829,7 @@ pos41503: if (A == 69) // 'T' { // Change T to CH - if (sam_debug) printf("RULE: T R -> CH R\n"); + if (DEBUG_ESP8266SAM_LIB) printf("RULE: T R -> CH R\n"); phonemeindex[pos-1] = 42; goto pos41779; } @@ -846,7 +844,7 @@ pos41503: { // Change D to J phonemeindex[pos-1] = 44; - if (sam_debug) printf("RULE: D R -> J R\n"); + if (DEBUG_ESP8266SAM_LIB) printf("RULE: D R -> J R\n"); goto pos41788; } @@ -857,7 +855,7 @@ pos41503: // If vowel flag is set change R to RX A = flags[A] & 128; - if (sam_debug) printf("RULE: R -> RX\n"); + if (DEBUG_ESP8266SAM_LIB) printf("RULE: R -> RX\n"); if (A != 0) phonemeindex[pos] = 18; // 'RX' // continue to next phoneme @@ -876,7 +874,7 @@ pos41611: // If prior phoneme does not have VOWEL flag set, move to next phoneme if ((flags[phonemeindex[pos-1]] & 128) == 0) {pos++; continue;} // Prior phoneme has VOWEL flag set, so change L to LX and move to next phoneme - if (sam_debug) printf("RULE: L -> LX\n"); + if (DEBUG_ESP8266SAM_LIB) printf("RULE: L -> LX\n"); phonemeindex[X] = 19; // 'LX' pos++; continue; @@ -895,7 +893,7 @@ pos41611: // If prior phoneme is not G, move to next phoneme if (phonemeindex[pos-1] != 60) {pos++; continue;} // Replace S with Z and move on - if (sam_debug) printf("RULE: G S -> G Z\n"); + if (DEBUG_ESP8266SAM_LIB) printf("RULE: G S -> G Z\n"); phonemeindex[pos] = 38; // 'Z' pos++; continue; @@ -916,7 +914,7 @@ pos41611: { // VOWELS AND DIPHTONGS ENDING WITH IY SOUND flag set? A = flags[Y] & 32; - if (sam_debug) if (A==0) printf("RULE: K -> KX \n"); + if (DEBUG_ESP8266SAM_LIB) if (A==0) printf("RULE: K -> KX \n"); // Replace with KX if (A == 0) phonemeindex[pos] = 75; // 'KX' } @@ -943,7 +941,7 @@ pos41611: // If diphtong ending with YX, move continue processing next phoneme if ((flags[index] & 32) != 0) {pos++; continue;} // replace G with GX and continue processing next phoneme - if (sam_debug) printf("RULE: G -> GX \n"); + if (DEBUG_ESP8266SAM_LIB) printf("RULE: G -> GX \n"); phonemeindex[pos] = 63; // 'GX' pos++; continue; @@ -968,7 +966,7 @@ pos41611: goto pos41812; } // Replace with softer version - if (sam_debug) printf("RULE: S* %c%c -> S* %c%c\n", signInputTable1[Y], signInputTable2[Y],signInputTable1[Y-12], signInputTable2[Y-12]); + if (DEBUG_ESP8266SAM_LIB) printf("RULE: S* %c%c -> S* %c%c\n", signInputTable1[Y], signInputTable2[Y],signInputTable1[Y-12], signInputTable2[Y-12]); phonemeindex[pos] = Y-12; pos++; continue; @@ -991,7 +989,7 @@ pos41749: A = flags2[Y] & 4; // If not set, continue processing next phoneme if (A == 0) {pos++; continue;} - if (sam_debug) printf("RULE: UW -> UX\n"); + if (DEBUG_ESP8266SAM_LIB) printf("RULE: UW -> UX\n"); phonemeindex[X] = 16; pos++; continue; @@ -1005,7 +1003,7 @@ pos41779: if (A == 42) // 'CH' { // pos41783: - if (sam_debug) printf("CH -> CH CH+1\n"); + if (DEBUG_ESP8266SAM_LIB) printf("CH -> CH CH+1\n"); Insert(X+1, A+1, mem59, stress[X]); pos++; continue; @@ -1020,7 +1018,7 @@ pos41788: if (A == 44) // 'J' { - if (sam_debug) printf("J -> J J+1\n"); + if (DEBUG_ESP8266SAM_LIB) printf("J -> J J+1\n"); Insert(X+1, A+1, mem59, stress[X]); pos++; continue; @@ -1060,7 +1058,7 @@ pos41812: if (stress[X] != 0) {pos++; continue;} //pos41856: // Set phonemes to DX - if (sam_debug) printf("RULE: Soften T or D following vowel or ER and preceding a pause -> DX\n"); + if (DEBUG_ESP8266SAM_LIB) printf("RULE: Soften T or D following vowel or ER and preceding a pause -> DX\n"); phonemeindex[pos] = 30; // 'DX' } else { @@ -1070,7 +1068,7 @@ pos41812: else // Is next phoneme a vowel or ER? A = flags[A] & 128; - if (sam_debug) if (A != 0) printf("RULE: Soften T or D following vowel or ER and preceding a pause -> DX\n"); + if (DEBUG_ESP8266SAM_LIB) if (A != 0) printf("RULE: Soften T or D following vowel or ER and preceding a pause -> DX\n"); if (A != 0) phonemeindex[pos] = 30; // 'DX' } @@ -1160,14 +1158,14 @@ pos48644: // change phoneme length to (length * 1.5) + 1 A = (A >> 1) + A + 1; -if (sam_debug) printf("RULE: Lengthen or between and by 1.5\n"); -if (sam_debug) printf("PRE\n"); -if (sam_debug) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); +if (DEBUG_ESP8266SAM_LIB) printf("RULE: Lengthen or between and by 1.5\n"); +if (DEBUG_ESP8266SAM_LIB) printf("PRE\n"); +if (DEBUG_ESP8266SAM_LIB) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); phonemeLength[X] = A; -if (sam_debug) printf("POST\n"); -if (sam_debug) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); +if (DEBUG_ESP8266SAM_LIB) printf("POST\n"); +if (DEBUG_ESP8266SAM_LIB) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); } // keep moving forward @@ -1221,15 +1219,15 @@ if (sam_debug) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonem // RULE: RX | LX -if (sam_debug) printf("RULE: - decrease length by 1\n"); -if (sam_debug) printf("PRE\n"); -if (sam_debug) printf("phoneme %d (%c%c) length %d\n", loopIndex, signInputTable1[phonemeindex[loopIndex]], signInputTable2[phonemeindex[loopIndex]], phonemeLength[loopIndex]); +if (DEBUG_ESP8266SAM_LIB) printf("RULE: - decrease length by 1\n"); +if (DEBUG_ESP8266SAM_LIB) printf("PRE\n"); +if (DEBUG_ESP8266SAM_LIB) printf("phoneme %d (%c%c) length %d\n", loopIndex, signInputTable1[phonemeindex[loopIndex]], signInputTable2[phonemeindex[loopIndex]], phonemeLength[loopIndex]); // decrease length of vowel by 1 frame phonemeLength[loopIndex]--; -if (sam_debug) printf("POST\n"); -if (sam_debug) printf("phoneme %d (%c%c) length %d\n", loopIndex, signInputTable1[phonemeindex[loopIndex]], signInputTable2[phonemeindex[loopIndex]], phonemeLength[loopIndex]); +if (DEBUG_ESP8266SAM_LIB) printf("POST\n"); +if (DEBUG_ESP8266SAM_LIB) printf("phoneme %d (%c%c) length %d\n", loopIndex, signInputTable1[phonemeindex[loopIndex]], signInputTable2[phonemeindex[loopIndex]], phonemeLength[loopIndex]); } // move ahead @@ -1267,16 +1265,16 @@ if (sam_debug) printf("phoneme %d (%c%c) length %d\n", loopIndex, signInputTable // move back X--; -if (sam_debug) printf("RULE: - decrease vowel by 1/8th\n"); -if (sam_debug) printf("PRE\n"); -if (sam_debug) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); +if (DEBUG_ESP8266SAM_LIB) printf("RULE: - decrease vowel by 1/8th\n"); +if (DEBUG_ESP8266SAM_LIB) printf("PRE\n"); +if (DEBUG_ESP8266SAM_LIB) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); // decrease length by 1/8th mem56 = phonemeLength[X] >> 3; phonemeLength[X] -= mem56; -if (sam_debug) printf("POST\n"); -if (sam_debug) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); +if (DEBUG_ESP8266SAM_LIB) printf("POST\n"); +if (DEBUG_ESP8266SAM_LIB) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); // move ahead loopIndex++; @@ -1286,16 +1284,16 @@ if (sam_debug) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonem // RULE: // -if (sam_debug) printf("RULE: - increase vowel by 1/2 + 1\n"); -if (sam_debug) printf("PRE\n"); -if (sam_debug) printf("phoneme %d (%c%c) length %d\n", X-1, signInputTable1[phonemeindex[X-1]], signInputTable2[phonemeindex[X-1]], phonemeLength[X-1]); +if (DEBUG_ESP8266SAM_LIB) printf("RULE: - increase vowel by 1/2 + 1\n"); +if (DEBUG_ESP8266SAM_LIB) printf("PRE\n"); +if (DEBUG_ESP8266SAM_LIB) printf("phoneme %d (%c%c) length %d\n", X-1, signInputTable1[phonemeindex[X-1]], signInputTable2[phonemeindex[X-1]], phonemeLength[X-1]); // decrease length A = phonemeLength[X-1]; phonemeLength[X-1] = (A >> 2) + A + 1; // 5/4*A + 1 -if (sam_debug) printf("POST\n"); -if (sam_debug) printf("phoneme %d (%c%c) length %d\n", X-1, signInputTable1[phonemeindex[X-1]], signInputTable2[phonemeindex[X-1]], phonemeLength[X-1]); +if (DEBUG_ESP8266SAM_LIB) printf("POST\n"); +if (DEBUG_ESP8266SAM_LIB) printf("phoneme %d (%c%c) length %d\n", X-1, signInputTable1[phonemeindex[X-1]], signInputTable2[phonemeindex[X-1]], phonemeLength[X-1]); // move ahead loopIndex++; @@ -1335,10 +1333,10 @@ if (sam_debug) printf("phoneme %d (%c%c) length %d\n", X-1, signInputTable1[phon // B*, D*, G*, GX, P*, T*, K*, KX { -if (sam_debug) printf("RULE: - set nasal = 5, consonant = 6\n"); -if (sam_debug) printf("POST\n"); -if (sam_debug) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); -if (sam_debug) printf("phoneme %d (%c%c) length %d\n", X-1, signInputTable1[phonemeindex[X-1]], signInputTable2[phonemeindex[X-1]], phonemeLength[X-1]); +if (DEBUG_ESP8266SAM_LIB) printf("RULE: - set nasal = 5, consonant = 6\n"); +if (DEBUG_ESP8266SAM_LIB) printf("POST\n"); +if (DEBUG_ESP8266SAM_LIB) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); +if (DEBUG_ESP8266SAM_LIB) printf("phoneme %d (%c%c) length %d\n", X-1, signInputTable1[phonemeindex[X-1]], signInputTable2[phonemeindex[X-1]], phonemeLength[X-1]); // set stop consonant length to 6 phonemeLength[X] = 6; @@ -1346,9 +1344,9 @@ if (sam_debug) printf("phoneme %d (%c%c) length %d\n", X-1, signInputTable1[phon // set nasal length to 5 phonemeLength[X-1] = 5; -if (sam_debug) printf("POST\n"); -if (sam_debug) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); -if (sam_debug) printf("phoneme %d (%c%c) length %d\n", X-1, signInputTable1[phonemeindex[X-1]], signInputTable2[phonemeindex[X-1]], phonemeLength[X-1]); +if (DEBUG_ESP8266SAM_LIB) printf("POST\n"); +if (DEBUG_ESP8266SAM_LIB) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); +if (DEBUG_ESP8266SAM_LIB) printf("phoneme %d (%c%c) length %d\n", X-1, signInputTable1[phonemeindex[X-1]], signInputTable2[phonemeindex[X-1]], phonemeLength[X-1]); } // move to next phoneme @@ -1388,10 +1386,10 @@ if (sam_debug) printf("phoneme %d (%c%c) length %d\n", X-1, signInputTable1[phon } // RULE: {optional silence} -if (sam_debug) printf("RULE: {optional silence} - shorten both to 1/2 + 1\n"); -if (sam_debug) printf("PRE\n"); -if (sam_debug) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); -if (sam_debug) printf("phoneme %d (%c%c) length %d\n", X-1, signInputTable1[phonemeindex[X-1]], signInputTable2[phonemeindex[X-1]], phonemeLength[X-1]); +if (DEBUG_ESP8266SAM_LIB) printf("RULE: {optional silence} - shorten both to 1/2 + 1\n"); +if (DEBUG_ESP8266SAM_LIB) printf("PRE\n"); +if (DEBUG_ESP8266SAM_LIB) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); +if (DEBUG_ESP8266SAM_LIB) printf("phoneme %d (%c%c) length %d\n", X-1, signInputTable1[phonemeindex[X-1]], signInputTable2[phonemeindex[X-1]], phonemeLength[X-1]); // X gets overwritten, so hold prior X value for debug statement int debugX = X; // shorten the prior phoneme length to (length/2 + 1) @@ -1401,9 +1399,9 @@ int debugX = X; // also shorten this phoneme length to (length/2 +1) phonemeLength[loopIndex] = (phonemeLength[loopIndex] >> 1) + 1; -if (sam_debug) printf("POST\n"); -if (sam_debug) printf("phoneme %d (%c%c) length %d\n", debugX, signInputTable1[phonemeindex[debugX]], signInputTable2[phonemeindex[debugX]], phonemeLength[debugX]); -if (sam_debug) printf("phoneme %d (%c%c) length %d\n", debugX-1, signInputTable1[phonemeindex[debugX-1]], signInputTable2[phonemeindex[debugX-1]], phonemeLength[debugX-1]); +if (DEBUG_ESP8266SAM_LIB) printf("POST\n"); +if (DEBUG_ESP8266SAM_LIB) printf("phoneme %d (%c%c) length %d\n", debugX, signInputTable1[phonemeindex[debugX]], signInputTable2[phonemeindex[debugX]], phonemeLength[debugX]); +if (DEBUG_ESP8266SAM_LIB) printf("phoneme %d (%c%c) length %d\n", debugX-1, signInputTable1[phonemeindex[debugX-1]], signInputTable2[phonemeindex[debugX-1]], phonemeLength[debugX-1]); // move ahead @@ -1429,15 +1427,15 @@ if (sam_debug) printf("phoneme %d (%c%c) length %d\n", debugX-1, signInputTable1 if((flags[index] & 2) != 0) // Rule: -if (sam_debug) printf("RULE: - decrease by 2\n"); -if (sam_debug) printf("PRE\n"); -if (sam_debug) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); +if (DEBUG_ESP8266SAM_LIB) printf("RULE: - decrease by 2\n"); +if (DEBUG_ESP8266SAM_LIB) printf("PRE\n"); +if (DEBUG_ESP8266SAM_LIB) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); // decrease the phoneme length by 2 frames (20 ms) phonemeLength[X] -= 2; -if (sam_debug) printf("POST\n"); -if (sam_debug) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); +if (DEBUG_ESP8266SAM_LIB) printf("POST\n"); +if (DEBUG_ESP8266SAM_LIB) printf("phoneme %d (%c%c) length %d\n", X, signInputTable1[phonemeindex[X]], signInputTable2[phonemeindex[X]], phonemeLength[X]); } // move to next phoneme