diff --git a/third-party/ArduinoJson/extras/tests/JsonArray/add.cpp b/third-party/ArduinoJson/extras/tests/JsonArray/add.cpp index 9b2f0b8..369bcf2 100644 --- a/third-party/ArduinoJson/extras/tests/JsonArray/add.cpp +++ b/third-party/ArduinoJson/extras/tests/JsonArray/add.cpp @@ -42,7 +42,7 @@ TEST_CASE("JsonArray::add()") { SECTION("vla") { size_t i = 16; char vla[i]; - strlcpy(vla, "world"); + strcpy(vla, "world"); array.add(vla); diff --git a/third-party/ArduinoJson/extras/tests/JsonArray/subscript.cpp b/third-party/ArduinoJson/extras/tests/JsonArray/subscript.cpp index 0211a9c..57bbe14 100644 --- a/third-party/ArduinoJson/extras/tests/JsonArray/subscript.cpp +++ b/third-party/ArduinoJson/extras/tests/JsonArray/subscript.cpp @@ -137,7 +137,7 @@ TEST_CASE("JsonArray::operator[]") { SECTION("set(VLA)") { size_t i = 16; char vla[i]; - strlcpy(vla, "world"); + strcpy(vla, "world"); array.add("hello"); array[0].set(vla); @@ -148,7 +148,7 @@ TEST_CASE("JsonArray::operator[]") { SECTION("operator=(VLA)") { size_t i = 16; char vla[i]; - strlcpy(vla, "world"); + strcpy(vla, "world"); array.add("hello"); array[0] = vla; diff --git a/third-party/ArduinoJson/extras/tests/JsonDeserializer/filter.cpp b/third-party/ArduinoJson/extras/tests/JsonDeserializer/filter.cpp index 0ad81f2..e0c3734 100644 --- a/third-party/ArduinoJson/extras/tests/JsonDeserializer/filter.cpp +++ b/third-party/ArduinoJson/extras/tests/JsonDeserializer/filter.cpp @@ -746,7 +746,7 @@ TEST_CASE("Overloads") { SECTION("char[n], Filter") { size_t i = 4; char vla[i]; - strlcpy(vla, "{}"); + strcpy(vla, "{}"); deserializeJson(doc, vla, Filter(filter)); } #endif @@ -774,7 +774,7 @@ TEST_CASE("Overloads") { SECTION("char[n], Filter, NestingLimit") { size_t i = 4; char vla[i]; - strlcpy(vla, "{}"); + strcpy(vla, "{}"); deserializeJson(doc, vla, Filter(filter), NestingLimit(5)); } #endif @@ -802,7 +802,7 @@ TEST_CASE("Overloads") { SECTION("char[n], NestingLimit, Filter") { size_t i = 4; char vla[i]; - strlcpy(vla, "{}"); + strcpy(vla, "{}"); deserializeJson(doc, vla, NestingLimit(5), Filter(filter)); } #endif diff --git a/third-party/ArduinoJson/extras/tests/JsonDeserializer/input_types.cpp b/third-party/ArduinoJson/extras/tests/JsonDeserializer/input_types.cpp index b98c215..04054c6 100644 --- a/third-party/ArduinoJson/extras/tests/JsonDeserializer/input_types.cpp +++ b/third-party/ArduinoJson/extras/tests/JsonDeserializer/input_types.cpp @@ -123,7 +123,7 @@ TEST_CASE("deserializeJson(std::istream&)") { TEST_CASE("deserializeJson(VLA)") { size_t i = 9; char vla[i]; - strlcpy(vla, "{\"a\":42}"); + strcpy(vla, "{\"a\":42}"); StaticJsonDocument doc; DeserializationError err = deserializeJson(doc, vla); diff --git a/third-party/ArduinoJson/extras/tests/JsonDocument/ElementProxy.cpp b/third-party/ArduinoJson/extras/tests/JsonDocument/ElementProxy.cpp index a98987c..eafc85f 100644 --- a/third-party/ArduinoJson/extras/tests/JsonDocument/ElementProxy.cpp +++ b/third-party/ArduinoJson/extras/tests/JsonDocument/ElementProxy.cpp @@ -27,7 +27,7 @@ TEST_CASE("ElementProxy::add()") { SECTION("set(char[])") { char s[] = "world"; ep.add(s); - strlcpy(s, "!!!!!"); + strcpy(s, "!!!!!"); REQUIRE(doc.as() == "[[\"world\"]]"); } @@ -133,7 +133,7 @@ TEST_CASE("ElementProxy::remove()") { size_t i = 4; char vla[i]; - strlcpy(vla, "b"); + strcpy(vla, "b"); ep.remove(vla); REQUIRE(ep.as() == "{\"a\":1}"); @@ -160,7 +160,7 @@ TEST_CASE("ElementProxy::set()") { SECTION("set(char[])") { char s[] = "world"; ep.set(s); - strlcpy(s, "!!!!!"); + strcpy(s, "!!!!!"); REQUIRE(doc.as() == "[\"world\"]"); } diff --git a/third-party/ArduinoJson/extras/tests/JsonDocument/MemberProxy.cpp b/third-party/ArduinoJson/extras/tests/JsonDocument/MemberProxy.cpp index 95b3db1..ed3e32b 100644 --- a/third-party/ArduinoJson/extras/tests/JsonDocument/MemberProxy.cpp +++ b/third-party/ArduinoJson/extras/tests/JsonDocument/MemberProxy.cpp @@ -174,7 +174,7 @@ TEST_CASE("MemberProxy::remove()") { size_t i = 4; char vla[i]; - strlcpy(vla, "b"); + strcpy(vla, "b"); mp.remove(vla); REQUIRE(mp.as() == "{\"a\":1}"); @@ -201,7 +201,7 @@ TEST_CASE("MemberProxy::set()") { SECTION("set(char[])") { // issue #1191 char s[] = "world"; mp.set(s); - strlcpy(s, "!!!!!"); + strcpy(s, "!!!!!"); REQUIRE(doc.as() == "{\"hello\":\"world\"}"); } diff --git a/third-party/ArduinoJson/extras/tests/JsonDocument/remove.cpp b/third-party/ArduinoJson/extras/tests/JsonDocument/remove.cpp index 742d2a5..b777073 100644 --- a/third-party/ArduinoJson/extras/tests/JsonDocument/remove.cpp +++ b/third-party/ArduinoJson/extras/tests/JsonDocument/remove.cpp @@ -43,7 +43,7 @@ TEST_CASE("JsonDocument::remove()") { size_t i = 4; char vla[i]; - strlcpy(vla, "b"); + strcpy(vla, "b"); doc.remove(vla); REQUIRE(doc.as() == "{\"a\":1}"); diff --git a/third-party/ArduinoJson/extras/tests/JsonObject/containsKey.cpp b/third-party/ArduinoJson/extras/tests/JsonObject/containsKey.cpp index 57ab5f3..4f37f7e 100644 --- a/third-party/ArduinoJson/extras/tests/JsonObject/containsKey.cpp +++ b/third-party/ArduinoJson/extras/tests/JsonObject/containsKey.cpp @@ -31,7 +31,7 @@ TEST_CASE("JsonObject::containsKey()") { SECTION("key is a VLA") { size_t i = 16; char vla[i]; - strlcpy(vla, "hello"); + strcpy(vla, "hello"); REQUIRE(true == obj.containsKey(vla)); } diff --git a/third-party/ArduinoJson/extras/tests/JsonObject/createNestedArray.cpp b/third-party/ArduinoJson/extras/tests/JsonObject/createNestedArray.cpp index 366b1c5..4d43038 100644 --- a/third-party/ArduinoJson/extras/tests/JsonObject/createNestedArray.cpp +++ b/third-party/ArduinoJson/extras/tests/JsonObject/createNestedArray.cpp @@ -18,7 +18,7 @@ TEST_CASE("JsonObject::createNestedArray()") { SECTION("key is a VLA") { size_t i = 16; char vla[i]; - strlcpy(vla, "hello"); + strcpy(vla, "hello"); JsonArray arr = obj.createNestedArray(vla); REQUIRE(arr.isNull() == false); diff --git a/third-party/ArduinoJson/extras/tests/JsonObject/createNestedObject.cpp b/third-party/ArduinoJson/extras/tests/JsonObject/createNestedObject.cpp index a48c672..29f4d39 100644 --- a/third-party/ArduinoJson/extras/tests/JsonObject/createNestedObject.cpp +++ b/third-party/ArduinoJson/extras/tests/JsonObject/createNestedObject.cpp @@ -17,7 +17,7 @@ TEST_CASE("JsonObject::createNestedObject()") { SECTION("key is a VLA") { size_t i = 16; char vla[i]; - strlcpy(vla, "hello"); + strcpy(vla, "hello"); obj.createNestedObject(vla); } diff --git a/third-party/ArduinoJson/extras/tests/JsonObject/remove.cpp b/third-party/ArduinoJson/extras/tests/JsonObject/remove.cpp index e5fb982..f1cb20c 100644 --- a/third-party/ArduinoJson/extras/tests/JsonObject/remove.cpp +++ b/third-party/ArduinoJson/extras/tests/JsonObject/remove.cpp @@ -62,7 +62,7 @@ TEST_CASE("JsonObject::remove()") { SECTION("key is a vla") { size_t i = 16; char vla[i]; - strlcpy(vla, "b"); + strcpy(vla, "b"); obj.remove(vla); serializeJson(obj, result); diff --git a/third-party/ArduinoJson/extras/tests/JsonObject/subscript.cpp b/third-party/ArduinoJson/extras/tests/JsonObject/subscript.cpp index f2dd909..e8242f6 100644 --- a/third-party/ArduinoJson/extras/tests/JsonObject/subscript.cpp +++ b/third-party/ArduinoJson/extras/tests/JsonObject/subscript.cpp @@ -174,7 +174,7 @@ TEST_CASE("JsonObject::operator[]") { SECTION("obj[VLA] = str") { size_t i = 16; char vla[i]; - strlcpy(vla, "hello"); + strcpy(vla, "hello"); obj[vla] = "world"; @@ -184,7 +184,7 @@ TEST_CASE("JsonObject::operator[]") { SECTION("obj[str] = VLA") { // issue #416 size_t i = 32; char vla[i]; - strlcpy(vla, "world"); + strcpy(vla, "world"); obj["hello"] = vla; @@ -194,7 +194,7 @@ TEST_CASE("JsonObject::operator[]") { SECTION("obj.set(VLA, str)") { size_t i = 16; char vla[i]; - strlcpy(vla, "hello"); + strcpy(vla, "hello"); obj[vla] = "world"; @@ -204,7 +204,7 @@ TEST_CASE("JsonObject::operator[]") { SECTION("obj.set(str, VLA)") { size_t i = 32; char vla[i]; - strlcpy(vla, "world"); + strcpy(vla, "world"); obj["hello"].set(vla); @@ -214,7 +214,7 @@ TEST_CASE("JsonObject::operator[]") { SECTION("obj[VLA]") { size_t i = 16; char vla[i]; - strlcpy(vla, "hello"); + strcpy(vla, "hello"); deserializeJson(doc, "{\"hello\":\"world\"}"); diff --git a/third-party/ArduinoJson/extras/tests/JsonVariant/set.cpp b/third-party/ArduinoJson/extras/tests/JsonVariant/set.cpp index b1626d1..9188c98 100644 --- a/third-party/ArduinoJson/extras/tests/JsonVariant/set.cpp +++ b/third-party/ArduinoJson/extras/tests/JsonVariant/set.cpp @@ -14,9 +14,9 @@ TEST_CASE("JsonVariant::set() when there is enough memory") { SECTION("const char*") { char str[16]; - strlcpy(str, "hello"); + strcpy(str, "hello"); bool result = variant.set(static_cast(str)); - strlcpy(str, "world"); + strcpy(str, "world"); REQUIRE(result == true); REQUIRE(variant == "world"); // stores by pointer @@ -32,9 +32,9 @@ TEST_CASE("JsonVariant::set() when there is enough memory") { SECTION("char*") { char str[16]; - strlcpy(str, "hello"); + strcpy(str, "hello"); bool result = variant.set(str); - strlcpy(str, "world"); + strcpy(str, "world"); REQUIRE(result == true); REQUIRE(variant == "hello"); // stores by copy @@ -50,9 +50,9 @@ TEST_CASE("JsonVariant::set() when there is enough memory") { SECTION("unsigned char*") { char str[16]; - strlcpy(str, "hello"); + strcpy(str, "hello"); bool result = variant.set(reinterpret_cast(str)); - strlcpy(str, "world"); + strcpy(str, "world"); REQUIRE(result == true); REQUIRE(variant == "hello"); // stores by copy @@ -61,9 +61,9 @@ TEST_CASE("JsonVariant::set() when there is enough memory") { SECTION("signed char*") { char str[16]; - strlcpy(str, "hello"); + strcpy(str, "hello"); bool result = variant.set(reinterpret_cast(str)); - strlcpy(str, "world"); + strcpy(str, "world"); REQUIRE(result == true); REQUIRE(variant == "hello"); // stores by copy @@ -74,9 +74,9 @@ TEST_CASE("JsonVariant::set() when there is enough memory") { size_t n = 16; char str[n]; - strlcpy(str, "hello"); + strcpy(str, "hello"); bool result = variant.set(str); - strlcpy(str, "world"); + strcpy(str, "world"); REQUIRE(result == true); REQUIRE(variant == "hello"); // stores by copy @@ -97,9 +97,9 @@ TEST_CASE("JsonVariant::set() when there is enough memory") { SECTION("static JsonString") { char str[16]; - strlcpy(str, "hello"); + strcpy(str, "hello"); bool result = variant.set(JsonString(str, JsonString::Linked)); - strlcpy(str, "world"); + strcpy(str, "world"); REQUIRE(result == true); REQUIRE(variant == "world"); // stores by pointer @@ -108,9 +108,9 @@ TEST_CASE("JsonVariant::set() when there is enough memory") { SECTION("non-static JsonString") { char str[16]; - strlcpy(str, "hello"); + strcpy(str, "hello"); bool result = variant.set(JsonString(str, JsonString::Copied)); - strlcpy(str, "world"); + strcpy(str, "world"); REQUIRE(result == true); REQUIRE(variant == "hello"); // stores by copy diff --git a/third-party/ArduinoJson/extras/tests/JsonVariant/subscript.cpp b/third-party/ArduinoJson/extras/tests/JsonVariant/subscript.cpp index 4b23aac..f466cd2 100644 --- a/third-party/ArduinoJson/extras/tests/JsonVariant/subscript.cpp +++ b/third-party/ArduinoJson/extras/tests/JsonVariant/subscript.cpp @@ -110,7 +110,7 @@ TEST_CASE("JsonVariant::operator[]") { SECTION("key is a VLA") { size_t i = 16; char vla[i]; - strlcpy(vla, "hello"); + strcpy(vla, "hello"); deserializeJson(doc, "{\"hello\":\"world\"}"); JsonVariant variant = doc.as(); @@ -121,7 +121,7 @@ TEST_CASE("JsonVariant::operator[]") { SECTION("key is a VLA, const JsonVariant") { size_t i = 16; char vla[i]; - strlcpy(vla, "hello"); + strcpy(vla, "hello"); deserializeJson(doc, "{\"hello\":\"world\"}"); const JsonVariant variant = doc.as(); diff --git a/third-party/ArduinoJson/extras/tests/MsgPackDeserializer/filter.cpp b/third-party/ArduinoJson/extras/tests/MsgPackDeserializer/filter.cpp index c98e0a3..57dd7be 100644 --- a/third-party/ArduinoJson/extras/tests/MsgPackDeserializer/filter.cpp +++ b/third-party/ArduinoJson/extras/tests/MsgPackDeserializer/filter.cpp @@ -1070,7 +1070,7 @@ TEST_CASE("Overloads") { SECTION("char[n], Filter") { size_t i = 4; char vla[i]; - strlcpy(vla, "{}"); + strcpy(vla, "{}"); deserializeMsgPack(doc, vla, Filter(filter)); } #endif @@ -1098,7 +1098,7 @@ TEST_CASE("Overloads") { SECTION("char[n], Filter, NestingLimit") { size_t i = 4; char vla[i]; - strlcpy(vla, "{}"); + strcpy(vla, "{}"); deserializeMsgPack(doc, vla, Filter(filter), NestingLimit(5)); } #endif @@ -1126,7 +1126,7 @@ TEST_CASE("Overloads") { SECTION("char[n], NestingLimit, Filter") { size_t i = 4; char vla[i]; - strlcpy(vla, "{}"); + strcpy(vla, "{}"); deserializeMsgPack(doc, vla, NestingLimit(5), Filter(filter)); } #endif diff --git a/third-party/LCDMenuLib2/src/LCDMenuLib2_macros.h b/third-party/LCDMenuLib2/src/LCDMenuLib2_macros.h index f840347..9a05569 100644 --- a/third-party/LCDMenuLib2/src/LCDMenuLib2_macros.h +++ b/third-party/LCDMenuLib2/src/LCDMenuLib2_macros.h @@ -97,13 +97,13 @@ const char g_LCDML_DISP_lang_ ## lang ## _ ## name ##_var[] = {content} #define LCDML_getCustomContent(lang, var, id) \ if(id < _LCDML_NO_FUNC) {\ - strlcpy(var, g_LCDML_DISP_lang_ ## lang ## _table[id]); \ + strcpy(var, g_LCDML_DISP_lang_ ## lang ## _table[id]); \ } #define LCDML_createCustomLang(N, lang) \ const char * g_LCDML_DISP_lang_ ## lang ## _table[] = { LCDML_DISP_lang_repeat(N, lang) } #define LCDML_getCustomElementName(lang, var, element_id) \ if(element_id < _LCDML_NO_FUNC && (sizeof(g_LCDML_DISP_lang_ ## lang ## _table)-1) >= element_id) {\ - strlcpy(var, g_LCDML_DISP_lang_ ## lang ## _table[element_id]);\ + strcpy(var, g_LCDML_DISP_lang_ ## lang ## _table[element_id]);\ } #else // stored in flash (Arduino) @@ -112,7 +112,7 @@ #define LCDML_getCustomContent(lang, var, id) \ if(id < _LCDML_NO_FUNC) {\ - strlcpy_P(var, (char*)pgm_read_word(&(g_LCDML_DISP_lang_ ## lang ## _table[id]))); \ + strcpy_P(var, (char*)pgm_read_word(&(g_LCDML_DISP_lang_ ## lang ## _table[id]))); \ } #define LCDML_createCustomLang(N, lang) \ @@ -120,7 +120,7 @@ #define LCDML_getCustomElementName(lang, var, element_id) \ if(element_id < _LCDML_NO_FUNC && (sizeof(g_LCDML_DISP_lang_ ## lang ## _table)-1) >= element_id) {\ - strlcpy_P(var, (char*)pgm_read_word(&(g_LCDML_DISP_lang_ ## lang ## _table[element_id])));\ + strcpy_P(var, (char*)pgm_read_word(&(g_LCDML_DISP_lang_ ## lang ## _table[element_id])));\ } #endif @@ -131,7 +131,7 @@ #define LCDML_getCustomContent(lang, var, id) \ if(id < _LCDML_NO_FUNC) {\ - strlcpy(var, g_LCDML_DISP_lang_ ## lang ## _table[id]); \ + strcpy(var, g_LCDML_DISP_lang_ ## lang ## _table[id]); \ } #define LCDML_createCustomLang(N, lang) \ @@ -139,7 +139,7 @@ #define LCDML_getCustomElementName(lang, var, element_id) \ if(element_id < _LCDML_NO_FUNC && (sizeof(g_LCDML_DISP_lang_ ## lang ## _table)-1) >= element_id) {\ - strlcpy(var, g_LCDML_DISP_lang_ ## lang ## _table[element_id]);\ + strcpy(var, g_LCDML_DISP_lang_ ## lang ## _table[element_id]);\ } #endif diff --git a/third-party/Synth_MDA_EPiano/src/mdaEPiano.cpp b/third-party/Synth_MDA_EPiano/src/mdaEPiano.cpp index 484c634..2ff51bb 100755 --- a/third-party/Synth_MDA_EPiano/src/mdaEPiano.cpp +++ b/third-party/Synth_MDA_EPiano/src/mdaEPiano.cpp @@ -116,7 +116,7 @@ mdaEPiano::mdaEPiano(uint8_t nvoices) // mdaEPiano::mdaEPiano(audioMasterCallbac void mdaEPiano::fillpatch(int32_t p, char *name, float p0, float p1, float p2, float p3, float p4, float p5, float p6, float p7, float p8, float p9, float p10,float p11) { - strlcpy(programs[p].name, name); + strlcpy(programs[p].name, name, sizeof(programs[p].name)); programs[p].param[0] = p0; programs[p].param[1] = p1; programs[p].param[2] = p2; programs[p].param[3] = p3; programs[p].param[4] = p4; programs[p].param[5] = p5; diff --git a/third-party/TeensyVariablePlayback/CMakeLists.txt b/third-party/TeensyVariablePlayback/CMakeLists.txt index ac6d954..575c3f6 100644 --- a/third-party/TeensyVariablePlayback/CMakeLists.txt +++ b/third-party/TeensyVariablePlayback/CMakeLists.txt @@ -15,11 +15,13 @@ if (NOT DEFINED BUILD_FOR_LINUX) import_arduino_library(Wire ${DEPSPATH}/Wire utility) import_arduino_library(arm_math ${DEPSPATH}/arm_math/src) import_arduino_library(Audio ${DEPSPATH}/Audio utility) + import_arduino_library(LittleFS ${DEPSPATH}/LittleFS/src littlefs) add_subdirectory(src) add_subdirectory(examples) else() add_subdirectory(src) add_subdirectory(test) + #add_subdirectory(extras/soundio/playqueue) add_subdirectory(extras/soundio/save_raw) add_subdirectory(extras/soundio/save_raw_sd) add_subdirectory(extras/soundio/save_wav) diff --git a/third-party/TeensyVariablePlayback/README.md b/third-party/TeensyVariablePlayback/README.md index 18010ea..04669e6 100644 --- a/third-party/TeensyVariablePlayback/README.md +++ b/third-party/TeensyVariablePlayback/README.md @@ -9,12 +9,20 @@ [![Commits](https://img.shields.io/github/commit-activity/m/newdigate/teensy-variable-playback)](https://github.com/newdigate/teensy-variable-playback/graphs/contributors) ![s](https://img.shields.io/badge/dynamic/json?color=%23e85b46&label=Patreon&query=data.attributes.patron_count&suffix=%20patrons&url=https%3A%2F%2Fwww.patreon.com%2Fapi%2Fcampaigns%2F4105381) -play 16-bit audio samples at variable playback rates on teensy +play 16-bit PCM raw or wav audio samples at variable playback rates on teensy +* **Note** : this library only works with signed 16-bit integer samples. Floating point samples will not play. * for best performance, use SDXC UHS 30MB/sec Application Performance Class 2 (A2) class micro sd-card. * [sd classes on wikipedia](https://en.wikipedia.org/wiki/SD_card#cite_ref-93) ## updates +* 16/06/2022: v1.0.14: + * refactored code to generic classes + * improve memory leaks + * remove calls to StartUsingSPI(), StopUsingSPI(), __disable_irq(), __enable_irq() + * intergated with SerialFlash and LittleFS +* 25/09/2021: v1.0.13: positionMillis() implemented for AudioPlaySdResmp +* 25/08/2021: v1.0.12: Skip over RIFF tags in .wav header * 12/08/2021: v1.0.11: When playing a mono sample, transmit on both channels (credit to @atoktoto) * 28/07/2021: v1.0.10: Fix issues when starting playback in reverse * 23/07/2021: v1.0.9: Fix issue which crashes teensy when playing multiple files from SD card using array of filenames @@ -100,10 +108,11 @@ graph G {
linux + You can run and test this code on your linux computer. You can write a teensy sketch, and with a few modifications, you can redirect the audio input and output to and from your soundcard. [Soundio](https://github.com/newdigate/teensy-audio-x86-stubs/tree/main/extras/soundio) bindings are optional, you can also run sketches and tests with no audio input or output. + You will need to install the following libraries. ```cmake``` ```gcc or llvm``` ```teensy-x86-stubs```[^](https://github.com/newdigate/teensy-x86-stubs) ```teensy-audio-x86-stubs```[^](https://github.com/newdigate/teensy-audio-x86-stubs) ```teensy-x86-sd-stubs```[^](https://github.com/newdigate/teensy-x86-sd-stubs) ```boost-test``` -By using stub libraries, we can compile teensy code to native device architecture. To a certain extent, this allows sketches and libraries to be developed, emulated, debugged and unit-tested using linux, on your local device or a build server. In this case I have a few basic tests for the ResamplingSdReader class. * install boost unit-test library: * linux: ```sudo apt-get install -yq libboost-test-dev``` * macos: ```brew install boost``` diff --git a/third-party/TeensyVariablePlayback/examples/CMakeLists.txt b/third-party/TeensyVariablePlayback/examples/CMakeLists.txt index b4d911d..8c0d1bc 100644 --- a/third-party/TeensyVariablePlayback/examples/CMakeLists.txt +++ b/third-party/TeensyVariablePlayback/examples/CMakeLists.txt @@ -1,6 +1,8 @@ cmake_minimum_required(VERSION 3.5) add_subdirectory(array) +add_subdirectory(LittleFS) add_subdirectory(sampleloader) add_subdirectory(sd_play_all) add_subdirectory(sd_raw) add_subdirectory(sd_wav) +add_subdirectory(SerialFlash) diff --git a/third-party/TeensyVariablePlayback/examples/LittleFS/CMakeLists.txt b/third-party/TeensyVariablePlayback/examples/LittleFS/CMakeLists.txt new file mode 100644 index 0000000..9951c6b --- /dev/null +++ b/third-party/TeensyVariablePlayback/examples/LittleFS/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.10) +project(sd_raw) +set(CMAKE_CXX_STANDARD 14) +add_definitions(-DPROG_FLASH_SIZE=10000) +teensy_include_directories(../../src) +teensy_add_executable(littlefs_raw littlefs_raw.ino) +teensy_target_link_libraries(littlefs_raw teensy_variable_playback SD SdFat Audio LittleFS SPI SerialFlash cores Wire arm_math) diff --git a/third-party/TeensyVariablePlayback/examples/LittleFS/littlefs_raw.ino b/third-party/TeensyVariablePlayback/examples/LittleFS/littlefs_raw.ino new file mode 100644 index 0000000..4da8c36 --- /dev/null +++ b/third-party/TeensyVariablePlayback/examples/LittleFS/littlefs_raw.ino @@ -0,0 +1,95 @@ +// Plays a RAW (16-bit signed) PCM audio file at slower or faster rate +// this example requires an uSD-card inserted to teensy 3.6 with a file called DEMO.RAW +#include +#include +#include +#include + +LittleFS_Program myfs; +#define PROG_FLASH_SIZE 1024 * 1024 * 1 // Specify size to use of onboard Teensy Program Flash chip + +// GUItool: begin automatically generated code +AudioPlayLfsResmp playLfsRaw1(myfs); //xy=324,457 +AudioOutputI2S i2s2; //xy=840.8571472167969,445.5714416503906 +AudioConnection patchCord1(playLfsRaw1, 0, i2s2, 0); +AudioConnection patchCord2(playLfsRaw1, 0, i2s2, 1); +AudioControlSGTL5000 audioShield; +// GUItool: end automatically generated code + +#define A14 10 + +const char* _filename = "DEMO.RAW"; +const int analogInPin = A14; +unsigned long lastSamplePlayed = 0; +uint32_t diskSize; + +double getPlaybackRate(int16_t analog) { //analog: 0..1023 + return (analog - 512.0) / 512.0; +} + +void setup() { + analogReference(0); + pinMode(analogInPin, INPUT_DISABLE); // i.e. Analog + + // see if the Flash is present and can be initialized: + // lets check to see if the T4 is setup for security first + #if ARDUINO_TEENSY40 + if ((IOMUXC_GPR_GPR11 & 0x100) == 0x100) { + //if security is active max disk size is 960x1024 + if (PROG_FLASH_SIZE > 960 * 1024) { + diskSize = 960 * 1024; + Serial.printf("Security Enables defaulted to %u bytes\n", diskSize); + } else { + diskSize = PROG_FLASH_SIZE; + Serial.printf("Security Not Enabled using %u bytes\n", diskSize); + } + } + #else + diskSize = PROG_FLASH_SIZE; + #endif + + // checks that the LittFS program has started with the disk size specified + if (!myfs.begin(diskSize)) { + Serial.printf("Error starting %s\n", "PROGRAM FLASH DISK"); + while (1) { + // Error, so don't do anything more - stay stuck here + } + } + Serial.println("LittleFS initialized."); + + audioShield.enable(); + audioShield.volume(0.5); + + playLfsRaw1.enableInterpolation(true); + int newsensorValue = analogRead(analogInPin); + playLfsRaw1.setPlaybackRate(getPlaybackRate(newsensorValue)); + + AudioMemory(24); +} + +void loop() { + + int newsensorValue = analogRead(analogInPin); + playLfsRaw1.setPlaybackRate(getPlaybackRate(newsensorValue)); + + unsigned currentMillis = millis(); + if (currentMillis > lastSamplePlayed + 500) { + if (!playLfsRaw1.isPlaying()) { + playLfsRaw1.playRaw(_filename, 1); + lastSamplePlayed = currentMillis; + + Serial.print("Memory: "); + Serial.print(AudioMemoryUsage()); + Serial.print(","); + Serial.print(AudioMemoryUsageMax()); + Serial.println(); + } + } + delay(10); +} + + +namespace std { + void __throw_bad_function_call() {} + void __throw_length_error(char const*) {} +} \ No newline at end of file diff --git a/third-party/TeensyVariablePlayback/examples/SerialFlash/CMakeLists.txt b/third-party/TeensyVariablePlayback/examples/SerialFlash/CMakeLists.txt new file mode 100644 index 0000000..f08e24c --- /dev/null +++ b/third-party/TeensyVariablePlayback/examples/SerialFlash/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.10) +project(serialflash_raw) +set(CMAKE_CXX_STANDARD 14) +add_definitions(-DPROG_FLASH_SIZE=10000) +teensy_include_directories(../../src) +teensy_add_executable(serialflash serialflash.ino) +teensy_target_link_libraries(serialflash teensy_variable_playback Audio SerialFlash SPI cores Wire arm_math) diff --git a/third-party/TeensyVariablePlayback/examples/SerialFlash/serialflash.ino b/third-party/TeensyVariablePlayback/examples/SerialFlash/serialflash.ino new file mode 100644 index 0000000..ea4e8f0 --- /dev/null +++ b/third-party/TeensyVariablePlayback/examples/SerialFlash/serialflash.ino @@ -0,0 +1,79 @@ +// Plays a RAW (16-bit signed) PCM audio file at slower or faster rate +// this example requires an uSD-card inserted to teensy 3.6 with a file called DEMO.RAW +#include +#include +#include +#include + +#define CSPIN 6 + +SerialFlashChip myfs; + +// GUItool: begin automatically generated code +AudioPlaySerialFlashResmp playSerialFlash1(myfs); //xy=324,457 +AudioOutputI2S i2s2; //xy=840.8571472167969,445.5714416503906 +AudioConnection patchCord1(playSerialFlash1, 0, i2s2, 0); +AudioConnection patchCord2(playSerialFlash1, 0, i2s2, 1); +AudioControlSGTL5000 audioShield; +// GUItool: end automatically generated code + +#define A14 10 + +const char* _filename = "DEMO.RAW"; +const int analogInPin = A14; +unsigned long lastSamplePlayed = 0; +uint32_t diskSize; + +double getPlaybackRate(int16_t analog) { //analog: 0..1023 + return (analog - 512.0) / 512.0; +} + +void setup() { + analogReference(0); + pinMode(analogInPin, INPUT_DISABLE); // i.e. Analog + + + if (!SerialFlash.begin(CSPIN)) { + while (1) { + Serial.println(F("Unable to access SPI Flash chip")); + delay(1000); + } + } + Serial.println("SerialFlash initialized."); + + audioShield.enable(); + audioShield.volume(0.5); + + playSerialFlash1.enableInterpolation(true); + int newsensorValue = analogRead(analogInPin); + playSerialFlash1.setPlaybackRate(getPlaybackRate(newsensorValue)); + + AudioMemory(24); +} + +void loop() { + + int newsensorValue = analogRead(analogInPin); + playSerialFlash1.setPlaybackRate(getPlaybackRate(newsensorValue)); + + unsigned currentMillis = millis(); + if (currentMillis > lastSamplePlayed + 500) { + if (!playSerialFlash1.isPlaying()) { + playSerialFlash1.playRaw(_filename, 1); + lastSamplePlayed = currentMillis; + + Serial.print("Memory: "); + Serial.print(AudioMemoryUsage()); + Serial.print(","); + Serial.print(AudioMemoryUsageMax()); + Serial.println(); + } + } + delay(10); +} + + +namespace std { + void __throw_bad_function_call() {} + void __throw_length_error(char const*) {} +} \ No newline at end of file diff --git a/third-party/TeensyVariablePlayback/examples/sd_play_all/sd_play_all.ino b/third-party/TeensyVariablePlayback/examples/sd_play_all/sd_play_all.ino index 560e593..41d190d 100644 --- a/third-party/TeensyVariablePlayback/examples/sd_play_all/sd_play_all.ino +++ b/third-party/TeensyVariablePlayback/examples/sd_play_all/sd_play_all.ino @@ -133,6 +133,7 @@ void populateFilenames(char *directory, char **filenames) { if ((m > 0 || a > 0) && (underscore != 0)) { filenames[index] = new char[curfile.length()+1] {0}; memcpy(filenames[index], curfile.c_str(), curfile.length()); + index++; } files.close(); } @@ -143,4 +144,4 @@ void populateFilenames(char *directory, char **filenames) { namespace std { void __throw_bad_function_call() {} void __throw_length_error(char const*) {} -} \ No newline at end of file +} diff --git a/third-party/TeensyVariablePlayback/library.json b/third-party/TeensyVariablePlayback/library.json index 2fa62d0..8c8b9c1 100644 --- a/third-party/TeensyVariablePlayback/library.json +++ b/third-party/TeensyVariablePlayback/library.json @@ -5,7 +5,7 @@ "keywords": "sound, audio, sample, resample, pitch, interpolation, legrange, sampler, playback, speed", "description": "Teensy Variable Playback", "url": "https://github.com/newdigate/teensy-variable-playback", - "version": "1.0.11", + "version": "1.0.14", "export": { "exclude": [ ".vscode", @@ -26,11 +26,10 @@ "type": "git", "url": "https://github.com/newdigate/teensy-variable-playback" }, - "dependencies": - { - "name": "Audio", - "frameworks": "arduino" - }, + "dependencies":[{ + "name": "Audio", + "frameworks": "arduino" + }], "examples": [ "examples/*/*.ino", "examples/*/*/*.ino" diff --git a/third-party/TeensyVariablePlayback/library.properties b/third-party/TeensyVariablePlayback/library.properties index c0c49c8..a75ee4c 100644 --- a/third-party/TeensyVariablePlayback/library.properties +++ b/third-party/TeensyVariablePlayback/library.properties @@ -1,5 +1,5 @@ name=TeensyVariablePlayback -version=1.0.11 +version=1.0.14 author=Nic Newdigate maintainer=Nic Newdigate sentence=Play samples at variable pitch using Teensy Audio Library diff --git a/third-party/TeensyVariablePlayback/src/CMakeLists.txt b/third-party/TeensyVariablePlayback/src/CMakeLists.txt index 365b7a3..cbb2657 100644 --- a/third-party/TeensyVariablePlayback/src/CMakeLists.txt +++ b/third-party/TeensyVariablePlayback/src/CMakeLists.txt @@ -3,12 +3,8 @@ project(teensy_variable_playback C CXX) set(teensy_variable_playback_VERSION 1.0.0) set(CMAKE_CXX_STANDARD 11) set(SOURCE_FILES - playsdresmp.cpp - ResamplingSdReader.cpp - ResamplingArrayReader.cpp - playarrayresmp.cpp interpolation.cpp - IndexableFile.cpp) + ) set(HEADER_FILES loop_type.h @@ -17,10 +13,19 @@ set(HEADER_FILES ResamplingSdReader.h waveheaderparser.h ResamplingArrayReader.h + ResamplingReader.h playarrayresmp.h interpolation.h TeensyVariablePlayback.h - IndexableFile.h) + IndexableFile.h + IndexableSerialFlashFile.h + IndexableLittleFSFile.h + IndexableSDFile.h + ResamplingLfsReader.h + ResamplingSerialFlashReader.h + playlfsresmp.h + playserialflashresmp.h + ) #set(CMAKE_VERBOSE_MAKEFILE 1) if (NOT DEFINED TEENSY_VERSION) diff --git a/third-party/TeensyVariablePlayback/src/IndexableFile.h b/third-party/TeensyVariablePlayback/src/IndexableFile.h index 9920f23..a4d4ea6 100644 --- a/third-party/TeensyVariablePlayback/src/IndexableFile.h +++ b/third-party/TeensyVariablePlayback/src/IndexableFile.h @@ -18,19 +18,24 @@ constexpr bool isPowerOf2(size_t value){ return !(value == 0) && !(value & (value - 1)); } -template // BUFFER_SIZE needs to be a power of two +template // BUFFER_SIZE needs to be a power of two class IndexableFile { public: static_assert(isPowerOf2(BUFFER_SIZE), "BUFFER_SIZE must be a power of 2"); + + virtual TFile open(const char *filename) = 0; static constexpr size_t element_size = sizeof(int16_t); size_t buffer_to_index_shift; - IndexableFile(File file) : + IndexableFile(const char *filename) : _buffers(), - buffer_to_index_shift(log2(BUFFER_SIZE)) { - _file = file; + buffer_to_index_shift(log2(BUFFER_SIZE)) + { + _filename = new char[strlen(filename)+1] {0}; + memcpy(_filename, filename, strlen(filename)); } - ~IndexableFile() { + + virtual ~IndexableFile() { close(); } @@ -49,12 +54,14 @@ public: next->buffer = new int16_t[BUFFER_SIZE]; size_t basePos = indexFor_i << buffer_to_index_shift; size_t seekPos = basePos * element_size; - - __disable_irq(); _file.seek(seekPos); int16_t bytesRead = _file.read(next->buffer, BUFFER_SIZE * element_size); - __enable_irq(); - + #ifndef TEENSYDUINO + if (!_file.available()){ + _file.close(); + _file = open(_filename); + } + #endif next->buffer_size = bytesRead; _buffers.push_back(next); match = next; @@ -63,20 +70,25 @@ public: } void close() { - if (_file.available()) { - __disable_irq(); + if (_file.available()) { _file.close(); - __enable_irq(); } - for (auto && x : _buffers){ + for (auto && x : _buffers){ delete [] x->buffer; delete x; } _buffers.clear(); + + if (_filename != nullptr) { + delete [] _filename; + _filename = nullptr; + } } -private: - File _file; + +protected: + TFile _file; + char *_filename; std::vector _buffers; indexedbuffer* find_with_index(uint32_t i) { @@ -91,4 +103,6 @@ private: } + + #endif diff --git a/third-party/TeensyVariablePlayback/src/IndexableLittleFSFile.h b/third-party/TeensyVariablePlayback/src/IndexableLittleFSFile.h new file mode 100644 index 0000000..e60ec3b --- /dev/null +++ b/third-party/TeensyVariablePlayback/src/IndexableLittleFSFile.h @@ -0,0 +1,43 @@ +#ifndef TEENSY_RESAMPLING_INDEXABLELITTLEFS_FILE_H +#define TEENSY_RESAMPLING_INDEXABLELITTLEFS_FILE_H + +#include +#include "IndexableFile.h" +#include +#include + +namespace newdigate { + +template // BUFFER_SIZE needs to be a power of two +class IndexableLittleFSFile : public IndexableFile { +public: + static_assert(isPowerOf2(BUFFER_SIZE), "BUFFER_SIZE must be a power of 2"); + + IndexableLittleFSFile(LittleFS &fs, const char *filename) : + IndexableFile(filename), + _myFS(fs) + { + IndexableFile::_file = _myFS.open(filename); + } + + File open(const char *filename) override { + return _myFS.open(filename); + } + + virtual ~IndexableLittleFSFile() { + IndexableFile::close(); + } + + int16_t &operator[](int i) { + return IndexableFile::operator[](i); + } + +private: + LittleFS &_myFS; +}; + +} + + + +#endif //TEENSY_RESAMPLING_INDEXABLELITTLEFS_FILE_H diff --git a/third-party/TeensyVariablePlayback/src/IndexableSDFile.h b/third-party/TeensyVariablePlayback/src/IndexableSDFile.h new file mode 100644 index 0000000..83eb218 --- /dev/null +++ b/third-party/TeensyVariablePlayback/src/IndexableSDFile.h @@ -0,0 +1,38 @@ +#ifndef TEENSY_RESAMPLING_INDEXABLESD_FILE_H +#define TEENSY_RESAMPLING_INDEXABLESD_FILE_H + +#include +#include "IndexableFile.h" +#include +#include + +namespace newdigate { + +template // BUFFER_SIZE needs to be a power of two +class IndexableSDFile : public IndexableFile { +public: + static_assert(isPowerOf2(BUFFER_SIZE), "BUFFER_SIZE must be a power of 2"); + + IndexableSDFile(const char *filename) : + IndexableFile(filename) { + IndexableFile::_file = open(filename); + } + + File open(const char *filename) override { + return SD.open(filename); + } + + virtual ~IndexableSDFile() { + IndexableFile::close(); + } + + int16_t &operator[](int i) { + return IndexableFile::operator[](i); + } +}; + +} + + + +#endif diff --git a/third-party/TeensyVariablePlayback/src/IndexableSerialFlashFile.h b/third-party/TeensyVariablePlayback/src/IndexableSerialFlashFile.h new file mode 100644 index 0000000..fc401aa --- /dev/null +++ b/third-party/TeensyVariablePlayback/src/IndexableSerialFlashFile.h @@ -0,0 +1,43 @@ +#ifndef TEENSY_RESAMPLING_INDEXABLESERIALFLASH_FILE_H +#define TEENSY_RESAMPLING_INDEXABLESERIALFLASH_FILE_H + +#include +#include "IndexableFile.h" +#include +#include + +namespace newdigate { + +template // BUFFER_SIZE needs to be a power of two +class IndexableSerialFlashFile : public IndexableFile { +public: + static_assert(isPowerOf2(BUFFER_SIZE), "BUFFER_SIZE must be a power of 2"); + + IndexableSerialFlashFile(SerialFlashChip &fs, const char *filename) : + IndexableFile(filename), + _myFS(fs) + { + IndexableFile::_file = _myFS.open(filename); + } + + SerialFlashFile open(const char *filename) override { + return _myFS.open(filename); + } + + virtual ~IndexableSerialFlashFile() { + IndexableFile::close(); + } + + int16_t &operator[](int i) { + return IndexableFile::operator[](i); + } + +private: + SerialFlashChip &_myFS; +}; + +} + + + +#endif //TEENSY_RESAMPLING_INDEXABLESERIALFLASH_FILE_H diff --git a/third-party/TeensyVariablePlayback/src/ResamplingArrayReader.h b/third-party/TeensyVariablePlayback/src/ResamplingArrayReader.h index bc2b5f5..5e87fb2 100644 --- a/third-party/TeensyVariablePlayback/src/ResamplingArrayReader.h +++ b/third-party/TeensyVariablePlayback/src/ResamplingArrayReader.h @@ -6,115 +6,44 @@ #include #include "loop_type.h" #include "interpolation.h" +#include "ResamplingReader.h" -class ResamplingArrayReader { -public: - ResamplingArrayReader() { - - } - - void begin(void); - bool playRaw(int16_t *array, uint32_t length, uint16_t numChannels); - bool playWav(int16_t *array, uint32_t length); - bool play(); - void stop(void); - bool isPlaying(void) { return _playing; } - - unsigned int read(void **buf, uint16_t nbyte); - bool readNextValue(int16_t *value, uint16_t channelNumber); - - void setPlaybackRate(double f) { - _playbackRate = f; - if (f < 0.0 && _bufferPosition == 0) { - //_file.seek(_file_size); - _bufferPosition = _file_size/2 - _numChannels; - } - } - - float playbackRate() { - return _playbackRate; - } - - void loop(uint32_t numSamples) { - __disable_irq(); - _loop_start = _bufferPosition; - _loop_finish = _bufferPosition + numSamples * _numChannels; - _loopType = loop_type::looptype_repeat; - __enable_irq(); - } +namespace newdigate { - void setLoopType(loop_type loopType) - { - _loopType = loopType; - } - - loop_type getLoopType(){ - return _loopType; - } - - int available(void); - void reset(void); - void close(void); - - void setLoopStart(uint32_t loop_start) { - _loop_start = _header_offset + (loop_start * _numChannels); +class ResamplingArrayReader : public ResamplingReader { +public: + ResamplingArrayReader() : + ResamplingReader() { + } + + virtual ~ResamplingArrayReader() { } - void setLoopFinish(uint32_t loop_finish) { - // sample number, (NOT byte number) - _loop_finish = _header_offset + (loop_finish * _numChannels); + int16_t getSourceBufferValue(long index) override { + return _sourceBuffer[index]; } - void setInterpolationType(ResampleInterpolationType interpolationType) { - if (interpolationType != _interpolationType) { - _interpolationType = interpolationType; - initializeInterpolationPoints(); - } + int available(void) { + return _playing; } - int16_t getNumChannels() { - return _numChannels; + int16_t* createSourceBuffer() override { + return _sourceBuffer; } - void setNumChannels(uint16_t numChannels) { - if (numChannels != _numChannels) { - _numChannels = numChannels; - initializeInterpolationPoints(); + void close(void) override { + if (_playing) { + stop(); + deleteInterpolationPoints(); } } - void setHeaderSizeInBytes(uint32_t headerSizeInBytes) { - _header_offset = headerSizeInBytes / 2; - if (_bufferPosition < _header_offset) { - if (_playbackRate >= 0) { - _bufferPosition = _header_offset; - } else - _bufferPosition = _loop_finish - _numChannels; - } + File open(char *filename) override { + return File(); } - -private: - volatile bool _playing = false; - - int32_t _file_size; - int32_t _header_offset = 0; // == (header size in bytes ) / 2 - - double _playbackRate = 1.0; - double _remainder = 0.0; - loop_type _loopType = looptype_none; - int _bufferPosition = 0; - int32_t _loop_start = 0; - int32_t _loop_finish = 0; - int16_t _numChannels = -1; - uint16_t _numInterpolationPointsChannels = 0; - int16_t *_sourceBuffer = nullptr; - - ResampleInterpolationType _interpolationType = ResampleInterpolationType::resampleinterpolation_none; - unsigned int _numInterpolationPoints = 0; - InterpolationData **_interpolationPoints = nullptr; - void initializeInterpolationPoints(void); - void deleteInterpolationPoints(void); +protected: }; +} #endif //TEENSYAUDIOLIBRARY_RESAMPLINGARRAYREADER_H diff --git a/third-party/TeensyVariablePlayback/src/ResamplingLfsReader.h b/third-party/TeensyVariablePlayback/src/ResamplingLfsReader.h new file mode 100644 index 0000000..d2ce8dc --- /dev/null +++ b/third-party/TeensyVariablePlayback/src/ResamplingLfsReader.h @@ -0,0 +1,78 @@ +// +// Created by Nicholas Newdigate on 10/02/2019. +// + +#ifndef TEENSYAUDIOLIBRARY_RESAMPLINGLFSREADER_H +#define TEENSYAUDIOLIBRARY_RESAMPLINGLFSREADER_H + +#include +#include "IndexableLittleFSFile.h" +#include "ResamplingReader.h" +#include "LittleFS.h" + +#define RESAMPLE_BUFFER_SAMPLE_SIZE 128 + +#define B2M (uint32_t)((double)4294967296000.0 / AUDIO_SAMPLE_RATE_EXACT / 2.0) // 97352592 + +namespace newdigate { + +class ResamplingLfsReader : public ResamplingReader< IndexableLittleFSFile<128, 2>, File > { +public: + ResamplingLfsReader(LittleFS &fs) : + ResamplingReader(), + _myFS(fs) + { + } + virtual ~ResamplingLfsReader() { + } + + int16_t getSourceBufferValue(long index) override { + return (*_sourceBuffer)[index]; + } + + int available(void) + { + return _playing; + } + + File open(char *filename) override { + return _myFS.open(filename); + } + + void close(void) override + { + if (_playing) + stop(); + if (_sourceBuffer != nullptr) { + _sourceBuffer->close(); + delete _sourceBuffer; + _sourceBuffer = nullptr; + } + if (_filename != nullptr) { + delete [] _filename; + _filename = nullptr; + } + deleteInterpolationPoints(); + } + + IndexableLittleFSFile<128, 2>* createSourceBuffer() override { + return new IndexableLittleFSFile<128, 2>(_myFS, _filename); + } + + uint32_t positionMillis(void) { + if (_file_size == 0) return 0; + + return (uint32_t) (( (double)_bufferPosition * lengthMillis() ) / (double)(_file_size/2)); + } + + uint32_t lengthMillis(void) { + return ((uint64_t)_file_size * B2M) >> 32; + } + +protected: + LittleFS &_myFS; +}; + +} + +#endif //TEENSYAUDIOLIBRARY_RESAMPLINGLFSREADER_H diff --git a/third-party/TeensyVariablePlayback/src/ResamplingReader.h b/third-party/TeensyVariablePlayback/src/ResamplingReader.h new file mode 100644 index 0000000..742bc6f --- /dev/null +++ b/third-party/TeensyVariablePlayback/src/ResamplingReader.h @@ -0,0 +1,500 @@ +#ifndef TEENSYAUDIOLIBRARY_RESAMPLINGREADER_H +#define TEENSYAUDIOLIBRARY_RESAMPLINGREADER_H + +#include +#include +#include "loop_type.h" +#include "interpolation.h" +#include "waveheaderparser.h" + +namespace newdigate { + +template +class ResamplingReader { +public: + ResamplingReader() { + } + virtual ~ResamplingReader() { + } + + virtual TFile open(char *filename) = 0; + virtual TArray* createSourceBuffer() = 0; + virtual int16_t getSourceBufferValue(long index) = 0; + virtual void close(void) = 0; + + void begin(void) + { + if (_interpolationType != ResampleInterpolationType::resampleinterpolation_none) { + initializeInterpolationPoints(); + } + _playing = false; + _bufferPosition = _header_offset; + _file_size = 0; + } + + bool playRaw(TArray *array, uint32_t length, uint16_t numChannels) + { + _sourceBuffer = array; + stop(); + + _header_offset = 0; + _file_size = length * 2; + _loop_start = 0; + _loop_finish = length; + setNumChannels(numChannels); + + reset(); + _playing = true; + return true; + } + + bool playRaw(TArray *array, uint16_t numChannels) { + return playRaw(array, false, numChannels); + } + + bool playWav(TArray *array, uint32_t length) { + return playRaw(array, true); + } + + bool play(const char *filename, bool isWave, uint16_t numChannelsIfRaw = 0) + { + close(); + + if (!isWave) // if raw file, then hardcode the numChannels as per the parameter + setNumChannels(numChannelsIfRaw); + + _filename = new char[strlen(filename)+1] {0}; + memcpy(_filename, filename, strlen(filename) + 1); + + TFile file = open(_filename); + if (!file) { + Serial.printf("Not able to open file: %s\n", _filename); + if (_filename) delete [] _filename; + _filename = nullptr; + return false; + } + + _file_size = file.size(); + if (isWave) { + wav_header wav_header; + wav_data_header data_header; + + WaveHeaderParser wavHeaderParser; + char buffer[36]; + size_t bytesRead = file.read(buffer, 36); + + wavHeaderParser.readWaveHeaderFromBuffer((const char *) buffer, wav_header); + if (wav_header.bit_depth != 16) { + Serial.printf("Needs 16 bit audio! Aborting.... (got %d)", wav_header.bit_depth); + return false; + } + setNumChannels(wav_header.num_channels); + + bytesRead = file.read(buffer, 8); + unsigned infoTagsSize; + if (!wavHeaderParser.readInfoTags((unsigned char *)buffer, 0, infoTagsSize)) + { + Serial.println("Not able to read header! Aborting..."); + return false; + } + + file.seek(36 + infoTagsSize); + bytesRead = file.read(buffer, 8); + + if (!wavHeaderParser.readDataHeader((unsigned char *)buffer, 0, data_header)) { + Serial.println("Not able to read header! Aborting..."); + return false; + } + + _header_offset = (44 + infoTagsSize) / 2; + _loop_finish = ((data_header.data_bytes) / 2) + _header_offset; + } else + _loop_finish = _file_size / 2; + + file.close(); + + if (_file_size <= _header_offset * sizeof(int16_t)) { + _playing = false; + if (_filename) delete [] _filename; + _filename = nullptr; + Serial.printf("Wave file contains no samples: %s\n", filename); + return false; + } + + _sourceBuffer = createSourceBuffer(); + _loop_start = _header_offset; + + reset(); + _playing = true; + return true; + } + + bool playRaw(const char *filename, uint16_t numChannelsIfRaw){ + return play(filename, false, numChannelsIfRaw); + } + + bool playWav(const char *filename){ + return play(filename, true); + } + + bool play() + { + stop(); + reset(); + _playing = true; + return true; + } + + void stop(void) + { + if (_playing) { + _playing = false; + } + } + + bool isPlaying(void) { return _playing; } + + unsigned int read(void **buf, uint16_t nsamples) { + if (!_playing) return 0; + + int16_t *index[_numChannels]; + unsigned int count = 0; + for (int channel=0; channel < _numChannels; channel++) { + index[channel] = (int16_t*)buf[channel]; + } + + while (count < nsamples) { + for (int channel=0; channel < _numChannels; channel++) { + if (readNextValue(index[channel], channel)) { + if (channel == _numChannels - 1) + count++; + index[channel]++; + } + else { + // we have reached the end of the file + + switch (_loopType) { + case looptype_repeat: + { + if (_playbackRate >= 0.0) + _bufferPosition = _loop_start; + else + _bufferPosition = _loop_finish - _numChannels; + + break; + } + + case looptype_pingpong: + { + if (_playbackRate >= 0.0) { + _bufferPosition = _loop_finish - _numChannels; + //printf("switching to reverse playback...\n"); + } + else { + _bufferPosition = _header_offset; + //printf("switching to forward playback...\n"); + } + _playbackRate = -_playbackRate; + break; + } + + case looptype_none: + default: + { + //Serial.printf("end of loop...\n"); + /* no looping - return the number of (resampled) bytes returned... */ + close(); + return count; + } + } + } + } + } + return count; + } + + // read the sample value for given channel and store it at the location pointed to by the pointer 'value' + bool readNextValue(int16_t *value, uint16_t channel) { + if (_playbackRate >= 0 ) { + //forward playback + if (_bufferPosition >= _loop_finish ) + return false; + + } else if (_playbackRate < 0) { + // reverse playback + if (_bufferPosition < _header_offset) + return false; + } + + + int16_t result = getSourceBufferValue(_bufferPosition + channel); + if (_interpolationType == ResampleInterpolationType::resampleinterpolation_linear) { + + double abs_remainder = abs(_remainder); + if (abs_remainder > 0.0) { + + if (_playbackRate > 0) { + if (_remainder - _playbackRate < 0.0){ + // we crossed over a whole number, make sure we update the samples for interpolation + + if (_playbackRate > 1.0) { + // need to update last sample + _interpolationPoints[channel][1].y = getSourceBufferValue(_bufferPosition-_numChannels); + } + + _interpolationPoints[channel][0].y = _interpolationPoints[channel][1].y; + _interpolationPoints[channel][1].y = result; + if (_numInterpolationPoints < 2) + _numInterpolationPoints++; + } + } + else if (_playbackRate < 0) { + if (_remainder - _playbackRate > 0.0){ + // we crossed over a whole number, make sure we update the samples for interpolation + + if (_playbackRate < -1.0) { + // need to update last sample + _interpolationPoints[channel][1].y = getSourceBufferValue(_bufferPosition+_numChannels); + } + + _interpolationPoints[channel][0].y = _interpolationPoints[channel][1].y; + _interpolationPoints[channel][1].y = result; + if (_numInterpolationPoints < 2) + _numInterpolationPoints++; + } + } + + if (_numInterpolationPoints > 1) { + result = abs_remainder * _interpolationPoints[channel][1].y + (1.0 - abs_remainder) * _interpolationPoints[channel][0].y; + //Serial.printf("[%f]\n", interpolation); + } + } else { + _interpolationPoints[channel][0].y = _interpolationPoints[channel][1].y; + _interpolationPoints[channel][1].y = result; + if (_numInterpolationPoints < 2) + _numInterpolationPoints++; + + result =_interpolationPoints[channel][0].y; + //Serial.printf("%f\n", result); + } + } + else if (_interpolationType == ResampleInterpolationType::resampleinterpolation_quadratic) { + double abs_remainder = abs(_remainder); + if (abs_remainder > 0.0) { + if (_playbackRate > 0) { + if (_remainder - _playbackRate < 0.0){ + // we crossed over a whole number, make sure we update the samples for interpolation + int numberOfSamplesToUpdate = - floor(_remainder - _playbackRate); + if (numberOfSamplesToUpdate > 4) + numberOfSamplesToUpdate = 4; // if playbackrate > 4, only need to pop last 4 samples + for (int i=numberOfSamplesToUpdate; i > 0; i--) { + _interpolationPoints[channel][0].y = _interpolationPoints[channel][1].y; + _interpolationPoints[channel][1].y = _interpolationPoints[channel][2].y; + _interpolationPoints[channel][2].y = _interpolationPoints[channel][3].y; + _interpolationPoints[channel][3].y = getSourceBufferValue(_bufferPosition-(i*_numChannels)+1+channel); + if (_numInterpolationPoints < 4) _numInterpolationPoints++; + } + } + } + else if (_playbackRate < 0) { + if (_remainder - _playbackRate > 0.0){ + // we crossed over a whole number, make sure we update the samples for interpolation + int numberOfSamplesToUpdate = ceil(_remainder - _playbackRate); + if (numberOfSamplesToUpdate > 4) + numberOfSamplesToUpdate = 4; // if playbackrate > 4, only need to pop last 4 samples + for (int i=numberOfSamplesToUpdate; i > 0; i--) { + _interpolationPoints[channel][0].y = _interpolationPoints[channel][1].y; + _interpolationPoints[channel][1].y = _interpolationPoints[channel][2].y; + _interpolationPoints[channel][2].y = _interpolationPoints[channel][3].y; + _interpolationPoints[channel][3].y = getSourceBufferValue(_bufferPosition+(i*_numChannels)-1+channel); + if (_numInterpolationPoints < 4) _numInterpolationPoints++; + } + } + } + + if (_numInterpolationPoints >= 4) { + //int16_t interpolation = interpolate(_interpolationPoints, 1.0 + abs_remainder, 4); + int16_t interpolation + = fastinterpolate( + _interpolationPoints[channel][0].y, + _interpolationPoints[channel][1].y, + _interpolationPoints[channel][2].y, + _interpolationPoints[channel][3].y, + 1.0 + abs_remainder); + result = interpolation; + //Serial.printf("[%f]\n", interpolation); + } else + result = 0; + } else { + _interpolationPoints[channel][0].y = _interpolationPoints[channel][1].y; + _interpolationPoints[channel][1].y = _interpolationPoints[channel][2].y; + _interpolationPoints[channel][2].y = _interpolationPoints[channel][3].y; + _interpolationPoints[channel][3].y = result; + if (_numInterpolationPoints < 4) { + _numInterpolationPoints++; + result = 0; + } else + result = _interpolationPoints[channel][1].y; + //Serial.printf("%f\n", result); + } + } + + if (channel == _numChannels - 1) { + _remainder += _playbackRate; + + auto delta = static_cast(_remainder); + _remainder -= static_cast(delta); + _bufferPosition += (delta * _numChannels); + } + + *value = result; + return true; + } + + void setPlaybackRate(double f) { + _playbackRate = f; + if (f < 0.0 && _bufferPosition == 0) { + //_file.seek(_file_size); + _bufferPosition = _file_size/2 - _numChannels; + } + } + + float playbackRate() { + return _playbackRate; + } + + void loop(uint32_t numSamples) { + _loop_start = _bufferPosition; + _loop_finish = _bufferPosition + numSamples * _numChannels; + _loopType = loop_type::looptype_repeat; + } + + void setLoopType(loop_type loopType) + { + _loopType = loopType; + } + + loop_type getLoopType() { + return _loopType; + } + + int available(void) { + return _playing; + } + + void reset(void) { + if (_interpolationType != ResampleInterpolationType::resampleinterpolation_none) { + initializeInterpolationPoints(); + } + _numInterpolationPoints = 0; + if (_playbackRate > 0.0) { + // forward playabck - set _file_offset to first audio block in file + _bufferPosition = _header_offset; + } else { + // reverse playback - forward _file_offset to last audio block in file + _bufferPosition = _loop_finish - _numChannels; + } + } + + void setLoopStart(uint32_t loop_start) { + _loop_start = _header_offset + (loop_start * _numChannels); + } + + void setLoopFinish(uint32_t loop_finish) { + // sample number, (NOT byte number) + _loop_finish = _header_offset + (loop_finish * _numChannels); + } + + void setInterpolationType(ResampleInterpolationType interpolationType) { + if (interpolationType != _interpolationType) { + _interpolationType = interpolationType; + initializeInterpolationPoints(); + } + } + + int16_t getNumChannels() { + return _numChannels; + } + + void setNumChannels(uint16_t numChannels) { + if (numChannels != _numChannels) { + _numChannels = numChannels; + initializeInterpolationPoints(); + } + } + + void setHeaderSizeInBytes(uint32_t headerSizeInBytes) { + _header_offset = headerSizeInBytes / 2; + if (_bufferPosition < _header_offset) { + if (_playbackRate >= 0) { + _bufferPosition = _header_offset; + } else + _bufferPosition = _loop_finish - _numChannels; + } + } + + #define B2M (uint32_t)((double)4294967296000.0 / AUDIO_SAMPLE_RATE_EXACT / 2.0) // 97352592 + uint32_t positionMillis() + { + return ((uint64_t)_file_size * B2M) >> 32; + } + + uint32_t lengthMillis() + { + return ((uint64_t)_file_size * B2M) >> 32; + } + +protected: + volatile bool _playing = false; + + int32_t _file_size; + int32_t _header_offset = 0; // == (header size in bytes ) / 2 + + double _playbackRate = 1.0; + double _remainder = 0.0; + loop_type _loopType = looptype_none; + int _bufferPosition = 0; + int32_t _loop_start = 0; + int32_t _loop_finish = 0; + int16_t _numChannels = -1; + uint16_t _numInterpolationPointsChannels = 0; + char *_filename = nullptr; + TArray *_sourceBuffer = nullptr; + + ResampleInterpolationType _interpolationType = ResampleInterpolationType::resampleinterpolation_none; + unsigned int _numInterpolationPoints = 0; + InterpolationData **_interpolationPoints = nullptr; + + void initializeInterpolationPoints(void) { + if (_numChannels < 0) + return; + + deleteInterpolationPoints(); + _interpolationPoints = new InterpolationData*[_numChannels]; + for (int channel=0; channel < _numChannels; channel++) { + InterpolationData *interpolation = new InterpolationData[4]; + interpolation[0].y = 0.0; + interpolation[1].y = 0.0; + interpolation[2].y = 0.0; + interpolation[3].y = 0.0; + _interpolationPoints[channel] = interpolation ; + } + _numInterpolationPointsChannels = _numChannels; + } + + void deleteInterpolationPoints(void) + { + if (!_interpolationPoints) return; + for (int i=0; i<_numInterpolationPointsChannels; i++) { + delete [] _interpolationPoints[i]; + } + delete [] _interpolationPoints; + _interpolationPoints = nullptr; + _numInterpolationPointsChannels = 0; + } + +}; + +} + +#endif //TEENSYAUDIOLIBRARY_RESAMPLINGREADER_H diff --git a/third-party/TeensyVariablePlayback/src/ResamplingSdReader.h b/third-party/TeensyVariablePlayback/src/ResamplingSdReader.h index 49ff25f..77c955d 100644 --- a/third-party/TeensyVariablePlayback/src/ResamplingSdReader.h +++ b/third-party/TeensyVariablePlayback/src/ResamplingSdReader.h @@ -10,143 +10,72 @@ #include "spi_interrupt.h" #include "loop_type.h" #include "interpolation.h" -#include "IndexableFile.h" +#include "IndexableSDFile.h" +#include "ResamplingReader.h" #define RESAMPLE_BUFFER_SAMPLE_SIZE 128 #define B2M (uint32_t)((double)4294967296000.0 / AUDIO_SAMPLE_RATE_EXACT / 2.0) // 97352592 -class ResamplingSdReader { +namespace newdigate { + +class ResamplingSdReader : public ResamplingReader< IndexableSDFile<128, 2>, File > { public: - ResamplingSdReader() { + ResamplingSdReader() : + ResamplingReader() + { } - - void begin(void); - bool playRaw(const char *filename, uint16_t numChannels); - bool playWav(const char *filename); - - bool play(); - void stop(void); - bool isPlaying(void) { return _playing; } - - unsigned int read(int16_t **buf); - bool readNextValue(int16_t *value, uint16_t channelNumber); - - void setPlaybackRate(double f) { - _playbackRate = f; - if (f < 0.0 && _bufferPosition == 0) { - //_file.seek(_file_size); - _bufferPosition = _file_size / 2 - _numChannels; - } + + virtual ~ResamplingSdReader() { } - double playbackRate() { - return _playbackRate; + int16_t getSourceBufferValue(long index) override { + return (*_sourceBuffer)[index]; } - void setLoopType(loop_type loopType) + int available(void) { - _loopType = loopType; + return _playing; } - loop_type getLoopType(){ - return _loopType; + File open(char *filename) override { + return SD.open(filename); } - int available(void); - void reset(void); - void close(void); - - void setLoopStart(uint32_t loop_start) { - _loop_start = _header_offset + (loop_start * _numChannels); - } - - void setLoopFinish(uint32_t loop_finish) { - // sample number, (NOT byte number) - _loop_finish = _header_offset + (loop_finish * _numChannels); - } - - void setInterpolationType(ResampleInterpolationType interpolationType) { - if (interpolationType != _interpolationType) { - _interpolationType = interpolationType; - initializeInterpolationPoints(); + void close(void) override + { + if (_playing) + stop(); + if (_sourceBuffer != nullptr) { + _sourceBuffer->close(); + delete _sourceBuffer; + _sourceBuffer = nullptr; } - } - - int16_t getNumChannels() { - return _numChannels; - } - - void setNumChannels(uint16_t numChannels) { - if (numChannels != _numChannels) { - _numChannels = numChannels; - initializeInterpolationPoints(); + if (_filename != nullptr) { + delete [] _filename; + _filename = nullptr; } + deleteInterpolationPoints(); } - void setHeaderSize(uint32_t headerSizeInBytes) { - _header_offset = headerSizeInBytes / 2; - if (_bufferPosition < _header_offset) { - if (_playbackRate >= 0) { - _bufferPosition = _header_offset; - } - } + IndexableSDFile<128, 2>* createSourceBuffer() override { + return new IndexableSDFile<128, 2>(_filename); } uint32_t positionMillis(void) { - return ((uint64_t) _file_size * B2M) >> 32; - } + if (_file_size == 0) return 0; - uint32_t lengthMillis(void) { - return ((uint64_t) _file_size * B2M) >> 32; - } -private: - volatile bool _playing = false; - - uint32_t _file_size; - uint32_t _header_offset = 0; // == (header size in bytes ) / 2 - - double _playbackRate = 1.0; - double _remainder = 0.0; - loop_type _loopType = looptype_none; - unsigned int _bufferPosition = 0; - uint32_t _loop_start = 0; - uint32_t _loop_finish = 0; - int16_t _numChannels = -1; - uint16_t _numInterpolationPointsChannels = 0; - newdigate::IndexableFile<128, 2> *_sourceBuffer = nullptr; - - ResampleInterpolationType _interpolationType = ResampleInterpolationType::resampleinterpolation_none; - unsigned int _numInterpolationPoints = 0; - InterpolationData **_interpolationPoints = nullptr; - - static bool isUsingSPI; - void StartUsingSPI(){ - if (!isUsingSPI) { - isUsingSPI = true; -#if defined(HAS_KINETIS_SDHC) - if (!(SIM_SCGC3 & SIM_SCGC3_SDHC)) AudioStartUsingSPI(); -#else - AudioStartUsingSPI(); -#endif - } + return (uint32_t) (( (double)_bufferPosition * lengthMillis() ) / (double)(_file_size/2)); } - void StopUsingSPI() { - if (isUsingSPI) { - isUsingSPI = false; -#if defined(HAS_KINETIS_SDHC) - if (!(SIM_SCGC3 & SIM_SCGC3_SDHC)) AudioStopUsingSPI(); -#else - AudioStopUsingSPI(); -#endif - } + uint32_t lengthMillis(void) { + return ((uint64_t)_file_size * B2M) >> 32; } - - bool play(const char *filename, bool isWave, uint16_t numChannelsIfRaw = 0); - void initializeInterpolationPoints(void); - void deleteInterpolationPoints(void); + +protected: + }; +} #endif //TEENSYAUDIOLIBRARY_RESAMPLINGSDREADER_H diff --git a/third-party/TeensyVariablePlayback/src/ResamplingSerialFlashReader.h b/third-party/TeensyVariablePlayback/src/ResamplingSerialFlashReader.h new file mode 100644 index 0000000..ca67e58 --- /dev/null +++ b/third-party/TeensyVariablePlayback/src/ResamplingSerialFlashReader.h @@ -0,0 +1,82 @@ +// +// Created by Nicholas Newdigate on 10/02/2019. +// + +#ifndef TEENSYAUDIOLIBRARY_RESAMPLINGSERIALFLASHREADER_H +#define TEENSYAUDIOLIBRARY_RESAMPLINGSERIALFLASHREADER_H + +#include +#include "spi_interrupt.h" +#include "loop_type.h" +#include "interpolation.h" +#include "IndexableSerialFlashFile.h" +#include "ResamplingReader.h" +#include "SerialFlash.h" + +#define RESAMPLE_BUFFER_SAMPLE_SIZE 128 + +#define B2M (uint32_t)((double)4294967296000.0 / AUDIO_SAMPLE_RATE_EXACT / 2.0) // 97352592 + +namespace newdigate { + +class ResamplingSerialFlashReader : public ResamplingReader< IndexableSerialFlashFile<128, 2>, SerialFlashFile > { +public: + ResamplingSerialFlashReader(SerialFlashChip &fs) : + ResamplingReader(), + _myFS(fs) + { + } + + virtual ~ResamplingSerialFlashReader() { + } + + int16_t getSourceBufferValue(long index) override { + return (*_sourceBuffer)[index]; + } + + int available(void) + { + return _playing; + } + + SerialFlashFile open(char *filename) override { + return _myFS.open(filename); + } + + void close(void) override + { + if (_playing) + stop(); + if (_sourceBuffer != nullptr) { + _sourceBuffer->close(); + delete _sourceBuffer; + _sourceBuffer = nullptr; + } + if (_filename != nullptr) { + delete [] _filename; + _filename = nullptr; + } + deleteInterpolationPoints(); + } + + IndexableSerialFlashFile<128, 2>* createSourceBuffer() override { + return new IndexableSerialFlashFile<128, 2>(_myFS, _filename); + } + + uint32_t positionMillis(void) { + if (_file_size == 0) return 0; + + return (uint32_t) (( (double)_bufferPosition * lengthMillis() ) / (double)(_file_size/2)); + } + + uint32_t lengthMillis(void) { + return ((uint64_t)_file_size * B2M) >> 32; + } + +protected: + SerialFlashChip &_myFS; +}; + +} + +#endif //TEENSYAUDIOLIBRARY_RESAMPLINGSERIALFLASHREADER_H diff --git a/third-party/TeensyVariablePlayback/src/TeensyVariablePlayback.h b/third-party/TeensyVariablePlayback/src/TeensyVariablePlayback.h index 75c53a3..eec731d 100644 --- a/third-party/TeensyVariablePlayback/src/TeensyVariablePlayback.h +++ b/third-party/TeensyVariablePlayback/src/TeensyVariablePlayback.h @@ -8,7 +8,10 @@ #include "waveheaderparser.h" #include "ResamplingSdReader.h" #include "ResamplingArrayReader.h" +#include "ResamplingLfsReader.h" +#include "ResamplingSerialFlashReader.h" #include "playsdresmp.h" #include "playarrayresmp.h" - +#include "playlfsresmp.h" +#include "playserialflashresmp.h" #endif //TEENSY_RESAMPLING_ARDUINO_SAMPLER_H diff --git a/third-party/TeensyVariablePlayback/src/playarrayresmp.h b/third-party/TeensyVariablePlayback/src/playarrayresmp.h index ff8e21a..4f37701 100644 --- a/third-party/TeensyVariablePlayback/src/playarrayresmp.h +++ b/third-party/TeensyVariablePlayback/src/playarrayresmp.h @@ -11,61 +11,19 @@ #include "ResamplingArrayReader.h" #include "playresmp.h" -class AudioPlayArrayResmp : public AudioPlayResmp +class AudioPlayArrayResmp : public AudioPlayResmp { public: AudioPlayArrayResmp(void) : - AudioPlayResmp(), - arrayReader() + AudioPlayResmp() { + reader = new newdigate::ResamplingArrayReader(); begin(); } - void begin(void); - bool playRaw(int16_t *data, uint32_t numSamples, uint16_t numChannels); - bool playRaw(const unsigned int *data, uint32_t numSamples, uint16_t numChannels); - - bool playWav(int16_t *data, uint32_t fileSize); - bool playWav(const unsigned int *data, uint32_t fileSize); - - void stop(void); - void close(void); - bool isPlaying(void) { return arrayReader.isPlaying(); } - uint32_t positionMillis(void); - uint32_t lengthMillis(void); - virtual void update(void); - - void setPlaybackRate(float f) { - arrayReader.setPlaybackRate(f); - } - - void setLoopType(loop_type t) { - arrayReader.setLoopType(t); - } - - void startLoop(uint32_t samples) { - arrayReader.loop(samples); - } - - void setLoopStart(uint32_t loop_start) { - arrayReader.setLoopStart(loop_start); + virtual ~AudioPlayArrayResmp() { + delete reader; } - - void setLoopFinish(uint32_t loop_finish) { - arrayReader.setLoopFinish(loop_finish); - } - - void enableInterpolation(bool enable) { - if (enable) - arrayReader.setInterpolationType(ResampleInterpolationType::resampleinterpolation_quadratic); - else - arrayReader.setInterpolationType(ResampleInterpolationType::resampleinterpolation_none); - } -private: - - uint32_t file_size; - ResamplingArrayReader arrayReader; - }; diff --git a/third-party/TeensyVariablePlayback/src/playlfsresmp.h b/third-party/TeensyVariablePlayback/src/playlfsresmp.h new file mode 100644 index 0000000..5774441 --- /dev/null +++ b/third-party/TeensyVariablePlayback/src/playlfsresmp.h @@ -0,0 +1,26 @@ +// +// Created by Nicholas Newdigate on 18/07/2020. +// + +#ifndef TEENSY_RESAMPLING_SDREADER_PLAYLFSRAWRESMP_H +#define TEENSY_RESAMPLING_SDREADER_PLAYLFSRAWRESMP_H + +#include "ResamplingLfsReader.h" + +class AudioPlayLfsResmp : public AudioPlayResmp +{ +public: + AudioPlayLfsResmp(LittleFS &fs) : + AudioPlayResmp() + { + reader = new newdigate::ResamplingLfsReader(fs); + begin(); + } + + virtual ~AudioPlayLfsResmp() { + delete reader; + } +}; + + +#endif //TEENSY_RESAMPLING_SDREADER_PLAYLFSRAWRESMP_H diff --git a/third-party/TeensyVariablePlayback/src/playresmp.h b/third-party/TeensyVariablePlayback/src/playresmp.h index 3d0ad3f..12df93f 100644 --- a/third-party/TeensyVariablePlayback/src/playresmp.h +++ b/third-party/TeensyVariablePlayback/src/playresmp.h @@ -5,20 +5,135 @@ #include "Audio.h" #include "loop_type.h" +template class AudioPlayResmp : public AudioStream { public: - AudioPlayResmp(void): AudioStream(0, NULL) {} - virtual ~AudioPlayResmp() {} - - virtual void setPlaybackRate(float f) = 0; - virtual void setLoopType(loop_type t) = 0; - virtual void setLoopStart(uint32_t loop_start) = 0; - virtual void setLoopFinish(uint32_t loop_finish) = 0; - virtual void begin() = 0; - virtual void enableInterpolation(bool enable) = 0; - virtual bool isPlaying(void) = 0; - virtual void stop() = 0; + AudioPlayResmp(): AudioStream(0, NULL), reader(nullptr) + { + } + + virtual ~AudioPlayResmp() { + } + + void begin(void) + { + reader->begin(); + } + + bool playRaw(const char *filename, uint16_t numChannels) + { + stop(); + return reader->play(filename, false, numChannels); + } + + bool playWav(const char *filename) + { + stop(); + return reader->play(filename, true, 0); + } + + bool playRaw(int16_t *data, uint32_t numSamples, uint16_t numChannels) + { + stop(); + return reader->playRaw(data, numSamples, numChannels); + } + + bool playRaw(const unsigned int *data, uint32_t numSamples, uint16_t numChannels) + { + return playRaw((int16_t *) data, numSamples, numChannels); + } + + bool playWav(int16_t *data, uint32_t fileSize) + { + stop(); + return reader->playWav(data, fileSize); + } + + bool playWav(const unsigned int *data, uint32_t fileSize) { + return playWav((int16_t *) data, fileSize); + } + + void setPlaybackRate(float f) { + reader->setPlaybackRate(f); + } + + void setLoopType(loop_type t) { + reader->setLoopType(t); + } + + void setLoopStart(uint32_t loop_start) { + reader->setLoopStart(loop_start); + } + + void setLoopFinish(uint32_t loop_finish) { + reader->setLoopFinish(loop_finish); + } + + void enableInterpolation(bool enable) { + if (enable) + reader->setInterpolationType(ResampleInterpolationType::resampleinterpolation_quadratic); + else + reader->setInterpolationType(ResampleInterpolationType::resampleinterpolation_none); + } + + bool isPlaying(void) { + return reader->isPlaying(); + }; + + void stop() { + reader->stop(); + } + + void update() + { + int _numChannels = reader->getNumChannels(); + if (_numChannels == -1) + return; + + unsigned int i, n; + audio_block_t *blocks[_numChannels]; + int16_t *data[_numChannels]; + // only update if we're playing + if (!reader->isPlaying()) return; + + // allocate the audio blocks to transmit + for (int i=0; i < _numChannels; i++) { + blocks[i] = allocate(); + if (blocks[i] == nullptr) return; + data[i] = blocks[i]->data; + } + + if (reader->available()) { + // we can read more data from the file... + n = reader->read((void**)data, AUDIO_BLOCK_SAMPLES); + for (int channel=0; channel < _numChannels; channel++) { + memset( &blocks[channel]->data[n], 0, (AUDIO_BLOCK_SAMPLES - n) * 2); + transmit(blocks[channel], channel); + } + + if(_numChannels == 1) { + transmit(blocks[0], 1); + } + } else { + reader->close(); + } + for (int channel=0; channel < _numChannels; channel++) { + release(blocks[channel]); + } + } + uint32_t positionMillis() + { + return reader->positionMillis(); + } + + uint32_t lengthMillis() + { + return reader->lengthMillis(); + } + + protected: + TResamplingReader *reader; }; #endif // TEENSY_RESAMPLING_SDREADER_PLAYRESMP_H \ No newline at end of file diff --git a/third-party/TeensyVariablePlayback/src/playsdresmp.h b/third-party/TeensyVariablePlayback/src/playsdresmp.h index faa2dfa..fdc039d 100644 --- a/third-party/TeensyVariablePlayback/src/playsdresmp.h +++ b/third-party/TeensyVariablePlayback/src/playsdresmp.h @@ -8,56 +8,24 @@ #include "Arduino.h" #include "AudioStream.h" +#include "SD.h" #include "stdint.h" #include "ResamplingSdReader.h" #include "playresmp.h" -class AudioPlaySdResmp : public AudioPlayResmp +class AudioPlaySdResmp : public AudioPlayResmp { public: AudioPlaySdResmp(void) : - AudioPlayResmp(), - sdReader() + AudioPlayResmp() { + reader = new newdigate::ResamplingSdReader(); begin(); } - void begin(void); - bool playRaw(const char *filename, uint16_t numChannels); - bool playWav(const char *filename); - void stop(void); - bool isPlaying(void) { return sdReader.isPlaying(); } - uint32_t positionMillis(void); - uint32_t lengthMillis(void); - virtual void update(void); - - void setPlaybackRate(float f) { - sdReader.setPlaybackRate(f); - } - - void setLoopType(loop_type t) { - sdReader.setLoopType(t); - } - - void setLoopStart(uint32_t loop_start) { - sdReader.setLoopStart(loop_start); + virtual ~AudioPlaySdResmp() { + delete reader; } - - void setLoopFinish(uint32_t loop_finish) { - sdReader.setLoopFinish(loop_finish); - } - - void enableInterpolation(bool enable) { - if (enable) - sdReader.setInterpolationType(ResampleInterpolationType::resampleinterpolation_quadratic); - else - sdReader.setInterpolationType(ResampleInterpolationType::resampleinterpolation_none); - } -private: - - uint32_t file_size; - ResamplingSdReader sdReader; - }; diff --git a/third-party/TeensyVariablePlayback/src/playserialflashresmp.h b/third-party/TeensyVariablePlayback/src/playserialflashresmp.h new file mode 100644 index 0000000..6dc56d5 --- /dev/null +++ b/third-party/TeensyVariablePlayback/src/playserialflashresmp.h @@ -0,0 +1,31 @@ +// +// Created by Nicholas Newdigate on 18/07/2020. +// + +#ifndef TEENSY_RESAMPLING_SDREADER_PLAYSERIALFLASHRAWRESMP_H +#define TEENSY_RESAMPLING_SDREADER_PLAYSERIALFLASHRAWRESMP_H + +#include "Arduino.h" +#include "AudioStream.h" +#include "SerialFlash.h" +#include "stdint.h" +#include "ResamplingSerialFlashReader.h" +#include "playresmp.h" + +class AudioPlaySerialFlashResmp : public AudioPlayResmp +{ +public: + AudioPlaySerialFlashResmp(SerialFlashChip &fs) : + AudioPlayResmp() + { + reader = new newdigate::ResamplingSerialFlashReader(fs); + begin(); + } + + virtual ~AudioPlaySerialFlashResmp() { + delete reader; + } +}; + + +#endif //TEENSY_RESAMPLING_SDREADER_PLAYSERIALFLASHRAWRESMP_H diff --git a/third-party/TeensyVariablePlayback/src/waveheaderparser.h b/third-party/TeensyVariablePlayback/src/waveheaderparser.h index 3dffb92..e8d7a56 100644 --- a/third-party/TeensyVariablePlayback/src/waveheaderparser.h +++ b/third-party/TeensyVariablePlayback/src/waveheaderparser.h @@ -14,47 +14,70 @@ using namespace std; // from https://gist.github.com/Jon-Schneider/8b7c53d27a7a13346a643dac9c19d34f struct wav_header { // RIFF Header - char riff_header[4]; // 00 - 03 - Contains "RIFF" - int header_chunk_size; // 04 - 07 - Size of the wav portion of the file, which follows the first 8 bytes. File size - 8 - char wave_header[4]; // 08 - 11 - Contains "WAVE" + char riff_header[4] = {0,0,0,0}; // 00 - 03 - Contains "RIFF" + int header_chunk_size = 0; // 04 - 07 - Size of the wav portion of the file, which follows the first 8 bytes. File size - 8 + char wave_header[4] = {0,0,0,0}; // 08 - 11 - Contains "WAVE" // Format Header - char fmt_header[4]; // 12 - 15 - Contains "fmt " (includes trailing space) - int fmt_chunk_size; // 16 - 19 - Should be 16 for PCM - short audio_format; // 20 - 21 - Should be 1 for PCM. 3 for IEEE Float - short num_channels; // 22 - 23 - int sample_rate; // 24 - 27 - int byte_rate; // 28 - 31 - short sample_alignment; // 32 - 33 - short bit_depth; // 34 - 35 + char fmt_header[4] = {0,0,0,0}; // 12 - 15 - Contains "fmt " (includes trailing space) + int fmt_chunk_size = 0; // 16 - 19 - Should be 16 for PCM + short audio_format = 0; // 20 - 21 - Should be 1 for PCM. 3 for IEEE Float + short num_channels = 0; // 22 - 23 + int sample_rate = 0; // 24 - 27 + int byte_rate = 0; // 28 - 31 + short sample_alignment = 0; // 32 - 33 + short bit_depth = 0; // 34 - 35 +}; +struct wav_data_header { // Data - char data_header[4]; // 36 - 39 - unsigned int data_bytes;// 40 - 43 + char data_header[4] = {0,0,0,0}; // 36 - 39 + unsigned int data_bytes = 0;// 40 - 43 }; class WaveHeaderParser { public: - bool readWaveHeader(const char *filename, wav_header &header, wav_header &wav_header) { - __disable_irq(); + bool readWaveHeader(const char *filename, wav_header &header, wav_data_header &wav_data_header) { File wavFile = SD.open(filename); - __enable_irq(); if (!wavFile) { - // Serial.printf("Not able to open wave file... %s\n", filename); + Serial.printf("Not able to open wave file... %s\n", filename); return false; } - bool result = readWaveHeader(header, wavFile); + bool result = readWaveHeader(filename, header, wavFile); + if (result) { + wavFile.seek(36); + unsigned char buffer[8]; + size_t bytesRead = wavFile.read(buffer, 8); + if (bytesRead != 8) { + Serial.printf("Not able to read header... %s\n", filename); + result = false; + } + + if (result) { + unsigned infoTagsSize; + result = readInfoTags(buffer, 0, infoTagsSize); + + if (result) { + wavFile.seek(36 + infoTagsSize); + bytesRead = wavFile.read(buffer, 8); + if (bytesRead != 8) { + Serial.printf("Not able to read header... %s\n", filename); + return false; + } + + result = readDataHeader(buffer, 0, wav_data_header); + } + } + } wavFile.close(); return result; } - bool readWaveHeader(wav_header &header, File wavFile) { - char buffer[44]; - __disable_irq(); - int bytesRead = wavFile.read(buffer, 44); - __enable_irq(); - if (bytesRead != 44) { - // Serial.printf("expected 44 bytes (was %d)\n", bytesRead); + bool readWaveHeader(const char *filename, wav_header &header, File &wavFile) { + char buffer[36]; + int bytesRead = wavFile.read(buffer, 36); + if (bytesRead != 36) { + Serial.printf("expected 36 bytes (was %d)\n", bytesRead); return false; } return readWaveHeaderFromBuffer(buffer, header); @@ -62,7 +85,7 @@ public: bool readWaveHeaderFromBuffer(const char *buffer, wav_header &header) { if (buffer[0] != 'R' || buffer[1] != 'I' || buffer[2] != 'F' || buffer[3] != 'F') { - // Serial.printf("expected RIFF (was %s)\n", buffer); + Serial.printf("expected RIFF (was %s)\n", buffer); return false; } for (int i=0; i < 4; i++) @@ -76,21 +99,21 @@ public: for (int i=0; i < 4; i++) header.wave_header[i] = buffer[i+8]; if (buffer[8] != 'W' || buffer[9] != 'A' || buffer[10] != 'V' || buffer[11] != 'E') { - // Serial.printf("expected WAVE (was %s)\n", buffer[8]); + Serial.printf("expected WAVE (was %s)\n", buffer[8]); return false; } for (int i=0; i < 4; i++) header.fmt_header[i] = buffer[i+12]; if (buffer[12] != 'f' || buffer[13] != 'm' || buffer[14] != 't' || buffer[15] != ' ') { - // Serial.printf("expected 'fmt ' (was %s)\n", buffer[12]); + Serial.printf("expected 'fmt ' (was %s)\n", buffer[12]); return false; } auto fmt_chunk_size = static_cast(b[19] << 24 | b[18] << 16 | b[17] << 8 | b[16]); header.fmt_chunk_size = fmt_chunk_size; if (fmt_chunk_size != 16) { - // Serial.printf("chunk size should be 16 for PCM wave data... (was %d)\n", fmt_chunk_size); + Serial.printf("chunk size should be 16 for PCM wave data... (was %d)\n", fmt_chunk_size); return false; } @@ -112,18 +135,45 @@ public: auto bit_depth = static_cast(b[35] << 8 | b[34]); header.bit_depth = bit_depth; - for (int i=0; i < 4; i++) - header.data_header[i] = buffer[i+36]; - if (buffer[36] != 'd' || buffer[37] != 'a' || buffer[38] != 't' || buffer[39] != 'a') { - // Serial.printf("expected data... (was %d)\n", buffer); + return true; + } + + bool readInfoTags(unsigned char *buffer, size_t offset, unsigned &infoTagsSize) { + if ( buffer[offset+0] == 'L' + && buffer[offset+1] == 'I' + && buffer[offset+2] == 'S' + && buffer[offset+3] == 'T') { + infoTagsSize = static_cast(buffer[offset+7] << 24 | buffer[offset+6] << 16 | buffer[offset+5] << 8 | buffer[offset+4]); + infoTagsSize += 8; + return true; + } + + if ( buffer[offset+0] == 'd' + && buffer[offset+1] == 'a' + && buffer[offset+2] == 't' + && buffer[offset+3] == 'a') { + infoTagsSize = 0; + return true; + } + + Serial.println("expected 'data' or 'LIST'..."); + return false; + } + + bool readDataHeader(unsigned char *buffer, size_t offset, wav_data_header &data_header) { + + for (int i=0; i < 4; i++) + data_header.data_header[i] = buffer[i+offset]; + + if (buffer[offset+0] != 'd' || buffer[offset+1] != 'a' || buffer[offset+2] != 't' || buffer[offset+3] != 'a') { + Serial.printf("expected data... (was %d)\n", buffer); return false; } - auto data_bytes = static_cast(b[43] << 24 | b[42] << 16 | b[41] << 8 | b[40]); - header.data_bytes = data_bytes; + auto data_bytes = static_cast(buffer[offset+7] << 24 | buffer[offset+6] << 16 | buffer[offset+5] << 8 | buffer[offset+4]); + data_header.data_bytes = data_bytes; return true; } - private: }; diff --git a/third-party/TeensyVariablePlayback/test/CMakeLists.txt b/third-party/TeensyVariablePlayback/test/CMakeLists.txt index b6116c3..74b6efc 100644 --- a/third-party/TeensyVariablePlayback/test/CMakeLists.txt +++ b/third-party/TeensyVariablePlayback/test/CMakeLists.txt @@ -57,6 +57,7 @@ if (DEFINED BUILD_FOR_LINUX) audio/wav/AudioWavFixture.h audio/wav/test_wav_mono_loop_forward_playback.cpp audio/wav/test_wav_stereo_loop_forward_playback.cpp + audio/wav/test_wav_tags.cpp low_level/sd/ResamplingReaderFixture.h low_level/sd/test_raw_mono_noloop_forward_playback.cpp diff --git a/third-party/TeensyVariablePlayback/test/audio/array/test_array_mono_loop_forward_playback.cpp b/third-party/TeensyVariablePlayback/test/audio/array/test_array_mono_loop_forward_playback.cpp index 5a5424a..0428821 100644 --- a/third-party/TeensyVariablePlayback/test/audio/array/test_array_mono_loop_forward_playback.cpp +++ b/third-party/TeensyVariablePlayback/test/audio/array/test_array_mono_loop_forward_playback.cpp @@ -14,6 +14,11 @@ extern unsigned int kick_raw_len; // in bytes, divide by 2 to get samples BOOST_AUTO_TEST_SUITE(test_audio_array_mono_loop_forward_playback) const uint16_t numberOfChannels = 1; + + const std::string referencePath = "test/resources/reference/"; + const std::string inputPath = "test/resources/input/"; + const std::string outputPath = "output/"; + BOOST_FIXTURE_TEST_CASE(Array_fwd_1_0000_quadratic_mono_noloop, AudioArrayFixture) { // GUItool: begin automatically generated code @@ -25,10 +30,10 @@ BOOST_AUTO_TEST_SUITE(test_audio_array_mono_loop_forward_playback) const double playbackRate = 1.0; const std::string testName = "Array_fwd_1_0000_quadratic_mono_noloop"; const std::string outputFile = testName+".wav"; - const std::string outputFileName = "output/" + outputFile; - const std::string referenceFileName = "test/resources/reference/"+testName+".wav"; + const std::string outputFileName = outputPath + outputFile; + const std::string referenceFileName = referencePath+testName+".wav"; - testout.saveOutputFile(outputFile.c_str()); + testout.saveOutputFile(outputPath.c_str(), outputFile.c_str()); memory.begin(); memory.enableInterpolation(true); memory.setPlaybackRate(playbackRate); @@ -59,10 +64,10 @@ BOOST_AUTO_TEST_SUITE(test_audio_array_mono_loop_forward_playback) const double playbackRate = 0.5; const std::string testName = "Array_fwd_0_5000_quadratic_mono_noloop"; const std::string outputFile = testName+".wav"; - const std::string outputFileName = "output/" + outputFile; - const std::string referenceFileName = "test/resources/reference/"+testName+".wav"; + const std::string outputFileName = outputPath + outputFile; + const std::string referenceFileName = referencePath+testName+".wav"; - testout.saveOutputFile(outputFile.c_str()); + testout.saveOutputFile(outputPath.c_str(), outputFile.c_str()); memory.begin(); memory.enableInterpolation(true); memory.setPlaybackRate(playbackRate); @@ -94,10 +99,10 @@ BOOST_AUTO_TEST_SUITE(test_audio_array_mono_loop_forward_playback) const double playbackRate = 2.0; const std::string testName = "Array_fwd_2_0000_quadratic_mono_noloop"; const std::string outputFile = testName+".wav"; - const std::string outputFileName = "output/" + outputFile; - const std::string referenceFileName = "test/resources/reference/"+testName+".wav"; + const std::string outputFileName = outputPath + outputFile; + const std::string referenceFileName = referencePath+testName+".wav"; - testout.saveOutputFile(outputFile.c_str()); + testout.saveOutputFile(outputPath.c_str(), outputFile.c_str()); memory.begin(); memory.enableInterpolation(true); memory.setPlaybackRate(playbackRate); @@ -129,10 +134,10 @@ BOOST_AUTO_TEST_SUITE(test_audio_array_mono_loop_forward_playback) const double playbackRate = 0.7437; const std::string testName = "Array_fwd_0_7437_quadratic_mono_noloop"; const std::string outputFile = testName+".wav"; - const std::string outputFileName = "output/" + outputFile; - const std::string referenceFileName = "test/resources/reference/"+testName+".wav"; + const std::string outputFileName = outputPath + outputFile; + const std::string referenceFileName = referencePath+testName+".wav"; - testout.saveOutputFile(outputFile.c_str()); + testout.saveOutputFile(outputPath.c_str(), outputFile.c_str()); memory.begin(); memory.enableInterpolation(true); memory.setPlaybackRate(playbackRate); @@ -165,10 +170,10 @@ BOOST_AUTO_TEST_SUITE(test_audio_array_mono_loop_forward_playback) const double playbackRate = 1.7437; const std::string testName = "Array_fwd_1_7437_quadratic_mono_noloop"; const std::string outputFile = testName+".wav"; - const std::string outputFileName = "output/" + outputFile; - const std::string referenceFileName = "test/resources/reference/"+testName+".wav"; + const std::string outputFileName = outputPath + outputFile; + const std::string referenceFileName = referencePath+testName+".wav"; - testout.saveOutputFile(outputFile.c_str()); + testout.saveOutputFile(outputPath.c_str(), outputFile.c_str()); memory.begin(); memory.enableInterpolation(true); memory.setPlaybackRate(playbackRate); @@ -200,10 +205,10 @@ BOOST_AUTO_TEST_SUITE(test_audio_array_mono_loop_forward_playback) const double playbackRate = 8.7437; const std::string testName = "Array_fwd_8_7437_quadratic_mono_noloop"; const std::string outputFile = testName+".wav"; - const std::string outputFileName = "output/" + outputFile; - const std::string referenceFileName = "test/resources/reference/"+testName+".wav"; + const std::string outputFileName = outputPath + outputFile; + const std::string referenceFileName = referencePath+testName+".wav"; - testout.saveOutputFile(outputFile.c_str()); + testout.saveOutputFile(outputPath.c_str(), outputFile.c_str()); memory.begin(); memory.enableInterpolation(true); memory.setPlaybackRate(playbackRate); diff --git a/third-party/TeensyVariablePlayback/test/audio/array/test_array_stereo_loop_forward_playback.cpp b/third-party/TeensyVariablePlayback/test/audio/array/test_array_stereo_loop_forward_playback.cpp index ad0c1e5..f0e83fc 100644 --- a/third-party/TeensyVariablePlayback/test/audio/array/test_array_stereo_loop_forward_playback.cpp +++ b/third-party/TeensyVariablePlayback/test/audio/array/test_array_stereo_loop_forward_playback.cpp @@ -14,6 +14,10 @@ extern unsigned int stereo_souljah_raw_len; BOOST_AUTO_TEST_SUITE(test_audio_array_stereo_loop_forward_playback) const uint16_t numberOfChannels = 2; + const std::string referencePath = "test/resources/reference/"; + const std::string inputPath = "test/resources/input/"; + const std::string outputPath = "output/"; + BOOST_FIXTURE_TEST_CASE(Array_fwd_1_0000_quadratic_stereo_noloop, AudioArrayFixture) { // GUItool: begin automatically generated code @@ -26,10 +30,10 @@ BOOST_AUTO_TEST_SUITE(test_audio_array_stereo_loop_forward_playback) const double playbackRate = 1.0; const std::string testName = "Array_fwd_1_0000_quadratic_stereo_noloop"; const std::string outputFile = testName+".wav"; - const std::string outputFileName = "output/" + outputFile; - const std::string referenceFileName = "test/resources/reference/"+testName+".wav"; - - testout.saveOutputFile(outputFile.c_str()); + const std::string outputFileName = outputPath + outputFile; + const std::string referenceFileName = referencePath+testName+".wav"; + + testout.saveOutputFile(outputPath.c_str(), outputFile.c_str()); memory.begin(); memory.enableInterpolation(true); memory.setPlaybackRate(playbackRate); @@ -61,10 +65,10 @@ BOOST_AUTO_TEST_SUITE(test_audio_array_stereo_loop_forward_playback) const double playbackRate = 0.5; const std::string testName = "Array_fwd_0_5000_quadratic_stereo_noloop"; const std::string outputFile = testName+".wav"; - const std::string outputFileName = "output/" + outputFile; - const std::string referenceFileName = "test/resources/reference/"+testName+".wav"; + const std::string outputFileName = outputPath + outputFile; + const std::string referenceFileName = referencePath+testName+".wav"; - testout.saveOutputFile(outputFile.c_str()); + testout.saveOutputFile(outputPath.c_str(), outputFile.c_str()); memory.begin(); memory.enableInterpolation(true); memory.setPlaybackRate(playbackRate); @@ -97,10 +101,10 @@ BOOST_AUTO_TEST_SUITE(test_audio_array_stereo_loop_forward_playback) const double playbackRate = 2.0; const std::string testName = "Array_fwd_2_0000_quadratic_stereo_noloop"; const std::string outputFile = testName+".wav"; - const std::string outputFileName = "output/" + outputFile; - const std::string referenceFileName = "test/resources/reference/"+testName+".wav"; + const std::string outputFileName = outputPath + outputFile; + const std::string referenceFileName = referencePath+testName+".wav"; - testout.saveOutputFile(outputFile.c_str()); + testout.saveOutputFile(outputPath.c_str(), outputFile.c_str()); memory.begin(); memory.enableInterpolation(true); memory.setPlaybackRate(playbackRate); @@ -133,10 +137,10 @@ BOOST_AUTO_TEST_SUITE(test_audio_array_stereo_loop_forward_playback) const double playbackRate = 0.7437; const std::string testName = "Array_fwd_0_7437_quadratic_stereo_noloop"; const std::string outputFile = testName+".wav"; - const std::string outputFileName = "output/" + outputFile; - const std::string referenceFileName = "test/resources/reference/"+testName+".wav"; + const std::string outputFileName = outputPath + outputFile; + const std::string referenceFileName = referencePath+testName+".wav"; - testout.saveOutputFile(outputFile.c_str()); + testout.saveOutputFile(outputPath.c_str(), outputFile.c_str()); memory.begin(); memory.enableInterpolation(true); memory.setPlaybackRate(playbackRate); @@ -170,10 +174,10 @@ BOOST_AUTO_TEST_SUITE(test_audio_array_stereo_loop_forward_playback) const double playbackRate = 1.7437; const std::string testName = "Array_fwd_1_7437_quadratic_stereo_noloop"; const std::string outputFile = testName+".wav"; - const std::string outputFileName = "output/" + outputFile; - const std::string referenceFileName = "test/resources/reference/"+testName+".wav"; + const std::string outputFileName = outputPath + outputFile; + const std::string referenceFileName = referencePath+testName+".wav"; - testout.saveOutputFile(outputFile.c_str()); + testout.saveOutputFile(outputPath.c_str(), outputFile.c_str()); memory.begin(); memory.enableInterpolation(true); memory.setPlaybackRate(playbackRate); @@ -206,10 +210,10 @@ BOOST_AUTO_TEST_SUITE(test_audio_array_stereo_loop_forward_playback) const double playbackRate = 8.7437; const std::string testName = "Array_fwd_8_7437_quadratic_stereo_noloop"; const std::string outputFile = testName+".wav"; - const std::string outputFileName = "output/" + outputFile; - const std::string referenceFileName = "test/resources/reference/"+testName+".wav"; + const std::string outputFileName = outputPath + outputFile; + const std::string referenceFileName = referencePath+testName+".wav"; - testout.saveOutputFile(outputFile.c_str()); + testout.saveOutputFile(outputPath.c_str(), outputFile.c_str()); memory.begin(); memory.enableInterpolation(true); memory.setPlaybackRate(playbackRate); diff --git a/third-party/TeensyVariablePlayback/test/audio/output_test.h b/third-party/TeensyVariablePlayback/test/audio/output_test.h index 5da06c3..f6f9745 100644 --- a/third-party/TeensyVariablePlayback/test/audio/output_test.h +++ b/third-party/TeensyVariablePlayback/test/audio/output_test.h @@ -21,33 +21,34 @@ public: virtual void update(void); void begin(void); static void isr(void); - void saveOutputFile(const char* filename){ - if (num_inputs == 0) return; + bool saveOutputFile(const char * path, const char* filename){ + if (num_inputs == 0) return false; char cwd[500]; if (getcwd(cwd, sizeof(cwd)) != NULL) { printf("Current working dir: %s\n", cwd); } else { perror("getcwd() error"); } - string outputPath = string(cwd) + "/output/"; + string outputPath = string(cwd) + "/" + string(path); __filesystem::path p(outputPath); if (! __filesystem::exists(p) ) __filesystem::create_directories(outputPath); - string filePath = outputPath + string(filename); - std::cout << "saving output audio .wav file to " << filePath << std::endl; - _outputFile.open(filePath); + _filePath = outputPath + string(filename); + std::cout << "saving output audio .wav file to " << _filePath << std::endl; + _outputFile.open(_filePath, ios_base::trunc | ios_base::out); if (!_outputFile.is_open()) { - Serial.println("couldn't open file for recording..."); + Serial.printf("couldn't open file for recording...%s\n", _filePath.c_str()); + return false; } else { _filename = filename; _outputFile.write((char*)test_output_wav_header, 44); - _saveToFile = true; + _saveToFile = true; + return true; } } void closeOutputfile(uint16_t numChannels) { if (!_saveToFile) return; - if (_outputFile.is_open()) { _saveToFile = false; char buf[4]; @@ -82,6 +83,7 @@ public: } protected: std::ofstream _outputFile; + std::string _filePath; static audio_block_t *block_left_1st; static audio_block_t *block_right_1st; static bool update_responsibility; diff --git a/third-party/TeensyVariablePlayback/test/audio/wav/test_wav_mono_loop_forward_playback.cpp b/third-party/TeensyVariablePlayback/test/audio/wav/test_wav_mono_loop_forward_playback.cpp index b26c2df..a771dd5 100644 --- a/third-party/TeensyVariablePlayback/test/audio/wav/test_wav_mono_loop_forward_playback.cpp +++ b/third-party/TeensyVariablePlayback/test/audio/wav/test_wav_mono_loop_forward_playback.cpp @@ -11,6 +11,11 @@ BOOST_AUTO_TEST_SUITE(test_audio_wav_mono_loop_forward_playback) const uint16_t numberOfChannels = 1; + + const std::string referencePath = "test/resources/reference/"; + const std::string inputPath = "test/resources/input/"; + const std::string outputPath = "output/"; + BOOST_FIXTURE_TEST_CASE(Wav_fwd_1_0000_quadratic_mono_noloop, AudioWavFixture) { // GUItool: begin automatically generated code @@ -18,15 +23,15 @@ BOOST_AUTO_TEST_SUITE(test_audio_wav_mono_loop_forward_playback) TestAudioOutput testout; //xy=612,224 AudioConnection patchCord1(wave, 0, testout, 0); // GUItool: end automatically generated code - + const double playbackRate = 1.0; const std::string testName = "Wav_fwd_1_0000_quadratic_mono_noloop"; const std::string outputFile = testName+".wav"; - const std::string outputFileName = "output/" + outputFile; - const std::string referencePath = "test/resources/reference/"; + const std::string outputFileName = outputPath + outputFile; const std::string referenceFileName = referencePath + testName + ".wav"; - SD.setSDCardFolderPath(referencePath); - testout.saveOutputFile(outputFile.c_str()); + SD.setSDCardFolderPath(inputPath); + + testout.saveOutputFile(outputPath.c_str(), outputFile.c_str()); wave.begin(); wave.enableInterpolation(true); @@ -58,12 +63,11 @@ BOOST_AUTO_TEST_SUITE(test_audio_wav_mono_loop_forward_playback) const double playbackRate = 0.5; const std::string testName = "Wav_fwd_0_5000_quadratic_mono_noloop"; const std::string outputFile = testName+".wav"; - const std::string outputFileName = "output/" + outputFile; - const std::string referencePath = "test/resources/reference/"; + const std::string outputFileName = outputPath + outputFile; const std::string referenceFileName = referencePath + testName + ".wav"; - SD.setSDCardFolderPath(referencePath); + SD.setSDCardFolderPath(inputPath); - testout.saveOutputFile(outputFile.c_str()); + testout.saveOutputFile(outputPath.c_str(), outputFile.c_str()); wave.begin(); wave.enableInterpolation(true); wave.setPlaybackRate(playbackRate); @@ -95,12 +99,11 @@ BOOST_AUTO_TEST_SUITE(test_audio_wav_mono_loop_forward_playback) const double playbackRate = 2.0; const std::string testName = "Wav_fwd_2_0000_quadratic_mono_noloop"; const std::string outputFile = testName+".wav"; - const std::string outputFileName = "output/" + outputFile; - const std::string referencePath = "test/resources/reference/"; + const std::string outputFileName = outputPath + outputFile; const std::string referenceFileName = referencePath + testName + ".wav"; - SD.setSDCardFolderPath(referencePath); + SD.setSDCardFolderPath(inputPath); - testout.saveOutputFile(outputFile.c_str()); + testout.saveOutputFile(outputPath.c_str(), outputFile.c_str()); wave.begin(); wave.enableInterpolation(true); wave.setPlaybackRate(playbackRate); @@ -132,12 +135,11 @@ BOOST_AUTO_TEST_SUITE(test_audio_wav_mono_loop_forward_playback) const double playbackRate = 0.7437; const std::string testName = "Wav_fwd_0_7437_quadratic_mono_noloop"; const std::string outputFile = testName+".wav"; - const std::string outputFileName = "output/" + outputFile; - const std::string referencePath = "test/resources/reference/"; + const std::string outputFileName = outputPath + outputFile; const std::string referenceFileName = referencePath + testName + ".wav"; - SD.setSDCardFolderPath(referencePath); + SD.setSDCardFolderPath(inputPath); - testout.saveOutputFile(outputFile.c_str()); + testout.saveOutputFile(outputPath.c_str(), outputFile.c_str()); wave.begin(); wave.enableInterpolation(true); wave.setPlaybackRate(playbackRate); @@ -170,12 +172,11 @@ BOOST_AUTO_TEST_SUITE(test_audio_wav_mono_loop_forward_playback) const double playbackRate = 1.7437; const std::string testName = "Wav_fwd_1_7437_quadratic_mono_noloop"; const std::string outputFile = testName+".wav"; - const std::string outputFileName = "output/" + outputFile; - const std::string referencePath = "test/resources/reference/"; + const std::string outputFileName = outputPath + outputFile; const std::string referenceFileName = referencePath + testName + ".wav"; - SD.setSDCardFolderPath(referencePath); + SD.setSDCardFolderPath(inputPath); - testout.saveOutputFile(outputFile.c_str()); + testout.saveOutputFile(outputPath.c_str(), outputFile.c_str()); wave.begin(); wave.enableInterpolation(true); wave.setPlaybackRate(playbackRate); @@ -207,10 +208,11 @@ BOOST_AUTO_TEST_SUITE(test_audio_wav_mono_loop_forward_playback) const double playbackRate = 8.7437; const std::string testName = "Wav_fwd_8_7437_quadratic_mono_noloop"; const std::string outputFile = testName+".wav"; - const std::string outputFileName = "output/" + outputFile; - const std::string referenceFileName = "test/resources/reference/"+testName+".wav"; + const std::string outputFileName = outputPath + outputFile; + const std::string referenceFileName = referencePath + testName + ".wav"; + SD.setSDCardFolderPath(inputPath); - testout.saveOutputFile(outputFile.c_str()); + testout.saveOutputFile(outputPath.c_str(), outputFile.c_str()); wave.begin(); wave.enableInterpolation(true); wave.setPlaybackRate(playbackRate); diff --git a/third-party/TeensyVariablePlayback/test/audio/wav/test_wav_stereo_loop_forward_playback.cpp b/third-party/TeensyVariablePlayback/test/audio/wav/test_wav_stereo_loop_forward_playback.cpp index 4902a0f..fa1738d 100644 --- a/third-party/TeensyVariablePlayback/test/audio/wav/test_wav_stereo_loop_forward_playback.cpp +++ b/third-party/TeensyVariablePlayback/test/audio/wav/test_wav_stereo_loop_forward_playback.cpp @@ -10,9 +10,12 @@ BOOST_AUTO_TEST_SUITE(test_audio_wav_stereo_loop_forward_playback) + const uint16_t numberOfChannels = 2; + const std::string referencePath = "test/resources/reference/"; + const std::string inputPath = "test/resources/input/"; + const std::string outputPath = "output/"; - const uint16_t numberOfChannels = 2; BOOST_FIXTURE_TEST_CASE(Wav_fwd_1_0000_quadratic_stereo_noloop, AudioWavFixture) { // GUItool: begin automatically generated code @@ -25,11 +28,11 @@ BOOST_AUTO_TEST_SUITE(test_audio_wav_stereo_loop_forward_playback) const double playbackRate = 1.0; const std::string testName = "Wav_fwd_1_0000_quadratic_stereo_noloop"; const std::string outputFile = testName+".wav"; - const std::string outputFileName = "output/" + outputFile; + const std::string outputFileName = outputPath + outputFile; const std::string referenceFileName = referencePath + testName + ".wav"; - SD.setSDCardFolderPath(referencePath); + SD.setSDCardFolderPath(inputPath); - testout.saveOutputFile(outputFile.c_str()); + testout.saveOutputFile(outputPath.c_str(), outputFile.c_str()); wave.begin(); wave.enableInterpolation(true); wave.setPlaybackRate(playbackRate); @@ -61,11 +64,11 @@ BOOST_AUTO_TEST_SUITE(test_audio_wav_stereo_loop_forward_playback) const double playbackRate = 0.5; const std::string testName = "Wav_fwd_0_5000_quadratic_stereo_noloop"; const std::string outputFile = testName+".wav"; - const std::string outputFileName = "output/" + outputFile; + const std::string outputFileName = outputPath + outputFile; const std::string referenceFileName = referencePath + testName + ".wav"; - SD.setSDCardFolderPath(referencePath); + SD.setSDCardFolderPath(inputPath); - testout.saveOutputFile(outputFile.c_str()); + testout.saveOutputFile(outputPath.c_str(), outputFile.c_str()); wave.begin(); wave.enableInterpolation(true); @@ -99,10 +102,11 @@ BOOST_AUTO_TEST_SUITE(test_audio_wav_stereo_loop_forward_playback) const double playbackRate = 2.0; const std::string testName = "Wav_fwd_2_0000_quadratic_stereo_noloop"; const std::string outputFile = testName+".wav"; - const std::string outputFileName = "output/" + outputFile; - const std::string referenceFileName = "test/resources/reference/"+testName+".wav"; + const std::string outputFileName = outputPath + outputFile; + const std::string referenceFileName = referencePath + testName + ".wav"; + SD.setSDCardFolderPath(inputPath); - testout.saveOutputFile(outputFile.c_str()); + testout.saveOutputFile(outputPath.c_str(), outputFile.c_str()); wave.begin(); wave.enableInterpolation(true); wave.setPlaybackRate(playbackRate); @@ -135,11 +139,11 @@ BOOST_AUTO_TEST_SUITE(test_audio_wav_stereo_loop_forward_playback) const double playbackRate = 0.7437; const std::string testName = "Wav_fwd_0_7437_quadratic_stereo_noloop"; const std::string outputFile = testName+".wav"; - const std::string outputFileName = "output/" + outputFile; + const std::string outputFileName = outputPath + outputFile; const std::string referenceFileName = referencePath + testName + ".wav"; - SD.setSDCardFolderPath(referencePath); + SD.setSDCardFolderPath(inputPath); - testout.saveOutputFile(outputFile.c_str()); + testout.saveOutputFile(outputPath.c_str(), outputFile.c_str()); wave.begin(); wave.enableInterpolation(true); wave.setPlaybackRate(playbackRate); @@ -173,11 +177,11 @@ BOOST_AUTO_TEST_SUITE(test_audio_wav_stereo_loop_forward_playback) const double playbackRate = 1.7437; const std::string testName = "Wav_fwd_1_7437_quadratic_stereo_noloop"; const std::string outputFile = testName+".wav"; - const std::string outputFileName = "output/" + outputFile; + const std::string outputFileName = outputPath + outputFile; const std::string referenceFileName = referencePath + testName + ".wav"; - SD.setSDCardFolderPath(referencePath); + SD.setSDCardFolderPath(inputPath); - testout.saveOutputFile(outputFile.c_str()); + testout.saveOutputFile(outputPath.c_str(), outputFile.c_str()); wave.begin(); wave.enableInterpolation(true); wave.setPlaybackRate(playbackRate); @@ -210,11 +214,11 @@ BOOST_AUTO_TEST_SUITE(test_audio_wav_stereo_loop_forward_playback) const double playbackRate = 8.7437; const std::string testName = "Wav_fwd_8_7437_quadratic_stereo_noloop"; const std::string outputFile = testName+".wav"; - const std::string outputFileName = "output/" + outputFile; + const std::string outputFileName = outputPath + outputFile; const std::string referenceFileName = referencePath + testName + ".wav"; - SD.setSDCardFolderPath(referencePath); + SD.setSDCardFolderPath(inputPath); - testout.saveOutputFile(outputFile.c_str()); + testout.saveOutputFile(outputPath.c_str(), outputFile.c_str()); wave.begin(); wave.enableInterpolation(true); wave.setPlaybackRate(playbackRate); diff --git a/third-party/TeensyVariablePlayback/test/audio/wav/test_wav_tags.cpp b/third-party/TeensyVariablePlayback/test/audio/wav/test_wav_tags.cpp new file mode 100644 index 0000000..5b9226a --- /dev/null +++ b/third-party/TeensyVariablePlayback/test/audio/wav/test_wav_tags.cpp @@ -0,0 +1,118 @@ +// +// Created by Nicholas Newdigate on 18/07/2020. +// + +#ifndef TEENSY_AUDIO_SDWAV_STEREO_READERTESTS_CPP +#define TEENSY_AUDIO_SDWAV_STEREO_READERTESTS_CPP + +#include +#include "AudioWavFixture.h" + +BOOST_AUTO_TEST_SUITE(test_audio_wav_tags_in_header) + + const uint16_t numberOfChannels = 2; + const std::string referencePath = "test/resources/reference/"; + const std::string inputPath = "test/resources/input/"; + const std::string outputPath = "output/"; + + BOOST_FIXTURE_TEST_CASE(Wav_with_tags_in_header_1, AudioWavFixture) { + + // GUItool: begin automatically generated code + AudioPlaySdResmp wave; //xy=306,225 + TestAudioOutput testout; //xy=612,224 + AudioConnection patchCord1(wave, 0, testout, 0); + AudioConnection patchCord2(wave, 1, testout, 1); + // GUItool: end automatically generated code + + const double playbackRate = 1.0; + const std::string testName = "SDTEST1"; + const std::string outputFile = testName+".wav"; + const std::string outputFileName = outputPath + outputFile; + const std::string referenceFileName = referencePath + testName + ".wav"; + SD.setSDCardFolderPath(inputPath); + + if (!testout.saveOutputFile(outputPath.c_str(), outputFile.c_str())) { + std::cout << "not able to save output file..." << std::endl; + BOOST_ERROR("not able to save output file (1)..."); + } + wave.begin(); + wave.enableInterpolation(true); + wave.setPlaybackRate(playbackRate); + bool isPlaying = wave.playWav(outputFile.c_str()); + if (!isPlaying) { + std::cout << "input audio file is not able to play..." << std::endl; + BOOST_ERROR("input audio file is not able to play (1)..."); + } + if (!wave.isPlaying()) { + std::cout << "input audio file is not able to play..." << std::endl; + BOOST_ERROR("input audio file is not able to play (2)..."); + } + + while (wave.isPlaying()) { + testout.isr(); + } + testout.closeOutputfile(numberOfChannels); + patchCord1.disconnect(); + AudioConnection::reset(); + arduino_should_exit = true; + + std::cout << "comparing " << outputFileName << " with " << referenceFileName << ";" << std::endl; + + std::ifstream ifs1(outputFileName); + std::ifstream ifs2(referenceFileName); + std::istream_iterator b1(ifs1), e1; + std::istream_iterator b2(ifs2), e2; + + BOOST_CHECK_EQUAL_COLLECTIONS(b1, e1, b2, e2); + } + BOOST_FIXTURE_TEST_CASE(Wav_with_tags_in_header_2, AudioWavFixture) { + + // GUItool: begin automatically generated code + AudioPlaySdResmp wave; //xy=306,225 + TestAudioOutput testout; //xy=612,224 + AudioConnection patchCord1(wave, 0, testout, 0); + AudioConnection patchCord2(wave, 1, testout, 1); + // GUItool: end automatically generated code + + const double playbackRate = 1.0; + const std::string testName = "SDTEST2"; + const std::string outputFile = testName+".wav"; + const std::string outputFileName = outputPath + outputFile; + const std::string referenceFileName = referencePath + testName + ".wav"; + SD.setSDCardFolderPath(inputPath); + + if (!testout.saveOutputFile(outputPath.c_str(), outputFile.c_str())) { + std::cout << "not able to save output file..." << std::endl; + BOOST_CHECK(false); + return; + } + wave.begin(); + wave.enableInterpolation(true); + wave.setPlaybackRate(playbackRate); + wave.playWav(outputFile.c_str()); + + if (!wave.isPlaying()) { + std::cout << "input audio file is not able to play..." << std::endl; + BOOST_CHECK(false); + return; + } + + while (wave.isPlaying()) { + testout.isr(); + } + testout.closeOutputfile(numberOfChannels); + patchCord1.disconnect(); + AudioConnection::reset(); + arduino_should_exit = true; + + std::ifstream ifs1(outputFileName); + std::ifstream ifs2(referenceFileName); + std::istream_iterator b1(ifs1), e1; + std::istream_iterator b2(ifs2), e2; + + BOOST_CHECK_EQUAL_COLLECTIONS(b1, e1, b2, e2); + } + +BOOST_AUTO_TEST_SUITE_END() + +#endif //TEENSY_AUDIO_SDWAV_STEREO_READERTESTS_CPP diff --git a/third-party/TeensyVariablePlayback/test/low_level/array/ResamplingArrayFixture.h b/third-party/TeensyVariablePlayback/test/low_level/array/ResamplingArrayFixture.h index d6df109..0490daf 100644 --- a/third-party/TeensyVariablePlayback/test/low_level/array/ResamplingArrayFixture.h +++ b/third-party/TeensyVariablePlayback/test/low_level/array/ResamplingArrayFixture.h @@ -10,14 +10,14 @@ struct ResamplingArrayFixture { ResamplingArrayFixture() { - resamplingArrayReader = new ResamplingArrayReader(); + resamplingArrayReader = new newdigate::ResamplingArrayReader(); } ~ResamplingArrayFixture() { delete resamplingArrayReader; } - ResamplingArrayReader * resamplingArrayReader; + newdigate::ResamplingArrayReader * resamplingArrayReader; }; #endif //TEENSY_RESAMPLING_SDREADER_RESAMPLINGARRAYFIXTURE_H diff --git a/third-party/TeensyVariablePlayback/test/low_level/arraywav/ResamplingArrayWavFixture.h b/third-party/TeensyVariablePlayback/test/low_level/arraywav/ResamplingArrayWavFixture.h index 9db4e38..f954704 100644 --- a/third-party/TeensyVariablePlayback/test/low_level/arraywav/ResamplingArrayWavFixture.h +++ b/third-party/TeensyVariablePlayback/test/low_level/arraywav/ResamplingArrayWavFixture.h @@ -10,14 +10,14 @@ struct ResamplingArrayWavFixture { ResamplingArrayWavFixture() { - resamplingArrayReader = new ResamplingArrayReader(); + resamplingArrayReader = new newdigate::ResamplingArrayReader(); } ~ResamplingArrayWavFixture() { delete resamplingArrayReader; } - ResamplingArrayReader * resamplingArrayReader; + newdigate::ResamplingArrayReader * resamplingArrayReader; }; #endif //TEENSY_RESAMPLING_SDREADER_RESAMPLINGARRAYWAVFIXTURE_H diff --git a/third-party/TeensyVariablePlayback/test/low_level/indexedfile/test_indexablefile.cpp b/third-party/TeensyVariablePlayback/test/low_level/indexedfile/test_indexablefile.cpp index 35c416c..017d38c 100644 --- a/third-party/TeensyVariablePlayback/test/low_level/indexedfile/test_indexablefile.cpp +++ b/third-party/TeensyVariablePlayback/test/low_level/indexedfile/test_indexablefile.cpp @@ -2,7 +2,7 @@ #include "IndexedFileFixture.h" #include -#include "IndexableFile.h" +#include "IndexableSDFile.h" BOOST_AUTO_TEST_SUITE(test_indexablefile) @@ -15,7 +15,7 @@ BOOST_AUTO_TEST_SUITE(test_indexablefile) } SD.setSDCardFileData((char*)file_contents, sample_size * 2); - newdigate::IndexableFile<16, 2> indexable("blah.h"); // use max 2 buffers, with 16 elements each.... + newdigate::IndexableSDFile<16, 2> indexable("blah.h"); // use max 2 buffers, with 16 elements each.... /* for (int i=0; ibegin(); resamplingSdReader->setPlaybackRate(1.0); - resamplingSdReader->playRaw("test2.bin", 1); + resamplingSdReader->play("test2.bin", false, 1); resamplingSdReader->setLoopType(looptype_none); resamplingSdReader->setInterpolationType(ResampleInterpolationType::resampleinterpolation_quadratic); int16_t actual[1024]; diff --git a/third-party/TeensyVariablePlayback/test/low_level/wav_header/test_parse_wave_header.cpp b/third-party/TeensyVariablePlayback/test/low_level/wav_header/test_parse_wave_header.cpp index 6487cdf..59096e2 100644 --- a/third-party/TeensyVariablePlayback/test/low_level/wav_header/test_parse_wave_header.cpp +++ b/third-party/TeensyVariablePlayback/test/low_level/wav_header/test_parse_wave_header.cpp @@ -23,7 +23,8 @@ BOOST_AUTO_TEST_SUITE(WaveHeaderParsingTests) SD.setSDCardFileData((char*) test_sndhdrdata_sndhdr_wav, test_sndhdrdata_sndhdr_wav_len); wav_header header; - bool success = waveHeaderParser->readWaveHeader("blah.wav", header); + wav_data_header data_header; + bool success = waveHeaderParser->readWaveHeader("blah.wav", header, data_header); BOOST_CHECK_EQUAL(success, true); const char expectedRIFF[5] = "RIFF"; BOOST_CHECK_EQUAL_COLLECTIONS(&header.riff_header[0], &header.riff_header[3],&expectedRIFF[0], &expectedRIFF[3]); @@ -33,7 +34,7 @@ BOOST_AUTO_TEST_SUITE(WaveHeaderParsingTests) const char expectedfmt[5] = "fmt "; BOOST_CHECK_EQUAL_COLLECTIONS(&header.fmt_header[0], &header.fmt_header[3],&expectedfmt[0], &expectedfmt[3]); const char expecteddata[5] = "data"; - BOOST_CHECK_EQUAL_COLLECTIONS(&header.data_header[0], &header.data_header[3],&expecteddata[0], &expecteddata[3]); + BOOST_CHECK_EQUAL_COLLECTIONS(&data_header.data_header[0], &data_header.data_header[3],&expecteddata[0], &expecteddata[3]); //BOOST_CHECK_EQUAL(File::numOpenFiles,0); //BOOST_CHECK_EQUAL(File::numInstances,0); } diff --git a/third-party/TeensyVariablePlayback/test/resources/input/SDTEST1.wav b/third-party/TeensyVariablePlayback/test/resources/input/SDTEST1.wav new file mode 100644 index 0000000..2b0d694 Binary files /dev/null and b/third-party/TeensyVariablePlayback/test/resources/input/SDTEST1.wav differ diff --git a/third-party/TeensyVariablePlayback/test/resources/input/SDTEST2.wav b/third-party/TeensyVariablePlayback/test/resources/input/SDTEST2.wav new file mode 100644 index 0000000..ff06d67 Binary files /dev/null and b/third-party/TeensyVariablePlayback/test/resources/input/SDTEST2.wav differ diff --git a/third-party/TeensyVariablePlayback/test/resources/input/kick.wav b/third-party/TeensyVariablePlayback/test/resources/input/kick.wav new file mode 100644 index 0000000..6e477c2 Binary files /dev/null and b/third-party/TeensyVariablePlayback/test/resources/input/kick.wav differ diff --git a/third-party/TeensyVariablePlayback/test/resources/reference/SDTEST1.wav b/third-party/TeensyVariablePlayback/test/resources/reference/SDTEST1.wav new file mode 100644 index 0000000..60793b6 Binary files /dev/null and b/third-party/TeensyVariablePlayback/test/resources/reference/SDTEST1.wav differ diff --git a/third-party/TeensyVariablePlayback/test/resources/reference/SDTEST2.wav b/third-party/TeensyVariablePlayback/test/resources/reference/SDTEST2.wav new file mode 100644 index 0000000..1fa5819 Binary files /dev/null and b/third-party/TeensyVariablePlayback/test/resources/reference/SDTEST2.wav differ diff --git a/third-party/effect_modulated_delay/src/effect_modulated_delay.cpp b/third-party/effect_modulated_delay/src/effect_modulated_delay.cpp index 9fa63ae..7e16d83 100644 --- a/third-party/effect_modulated_delay/src/effect_modulated_delay.cpp +++ b/third-party/effect_modulated_delay/src/effect_modulated_delay.cpp @@ -22,7 +22,6 @@ */ #include -#include "config.h" #include #include "arm_math.h" #include "effect_modulated_delay.h" diff --git a/third-party/effect_modulated_delay/src/effect_modulated_delay.h b/third-party/effect_modulated_delay/src/effect_modulated_delay.h index aae76ac..bb96e03 100644 --- a/third-party/effect_modulated_delay/src/effect_modulated_delay.h +++ b/third-party/effect_modulated_delay/src/effect_modulated_delay.h @@ -26,7 +26,6 @@ #include "Arduino.h" #include "AudioStream.h" -#include "config.h" /*************************************************************************/ // A u d i o E f f e c t M o d u l a t e d D e l a y