From acf9e11d5f9f60e188635de1714064fc00aa02f7 Mon Sep 17 00:00:00 2001 From: soyer Date: Mon, 21 Apr 2025 23:39:42 +0200 Subject: [PATCH 1/4] Use SoundFormatSigned24_32 with NEON (#852) * use SoundFormatSigned24_32 format instead of SoundFormatSigned16 More detailed, and not much slower. * fix ARM_MATH_NEON defines --------- Co-authored-by: probonopd --- src/Makefile | 1 + src/Synth_Dexed.mk | 3 +- src/arm_float_to_q23.c | 88 ++++++++++++++++++++++++++++++++++++++++++ src/arm_float_to_q23.h | 22 +++++++++++ src/minidexed.cpp | 19 ++++----- 5 files changed, 123 insertions(+), 10 deletions(-) create mode 100644 src/arm_float_to_q23.c create mode 100644 src/arm_float_to_q23.h diff --git a/src/Makefile b/src/Makefile index 7882018..73dbddc 100644 --- a/src/Makefile +++ b/src/Makefile @@ -10,6 +10,7 @@ OBJS = main.o kernel.o minidexed.o config.o userinterface.o uimenu.o \ mididevice.o midikeyboard.o serialmididevice.o pckeyboard.o \ sysexfileloader.o performanceconfig.o perftimer.o \ effect_compressor.o effect_platervbstereo.o uibuttons.o midipin.o \ + arm_float_to_q23.o \ net/ftpdaemon.o net/ftpworker.o net/applemidi.o net/udpmidi.o net/mdnspublisher.o udpmididevice.o OPTIMIZE = -O3 diff --git a/src/Synth_Dexed.mk b/src/Synth_Dexed.mk index 6aa4a49..4d42e67 100644 --- a/src/Synth_Dexed.mk +++ b/src/Synth_Dexed.mk @@ -40,8 +40,9 @@ INCLUDE += -I $(CMSIS_DSP_COMPUTELIB_INCLUDE_DIR) DEFINE += -DUSE_FX -ifeq ($(strip $(AARCH)),64) +ifeq ($(RPI), $(filter $(RPI), 3 4 5)) DEFINE += -DARM_MATH_NEON +DEFINE += -DARM_MATH_NEON_EXPERIMENTAL DEFINE += -DHAVE_NEON endif diff --git a/src/arm_float_to_q23.c b/src/arm_float_to_q23.c new file mode 100644 index 0000000..8eb21be --- /dev/null +++ b/src/arm_float_to_q23.c @@ -0,0 +1,88 @@ +#include "arm_float_to_q23.h" + +#if defined(ARM_MATH_NEON_EXPERIMENTAL) +void arm_float_to_q23(const float32_t * pSrc, q23_t * pDst, uint32_t blockSize) +{ + const float32_t *pIn = pSrc; /* Src pointer */ + uint32_t blkCnt; /* loop counter */ + + float32x4_t inV; + + int32x4_t cvt; + + blkCnt = blockSize >> 2U; + + /* Compute 4 outputs at a time. + ** a second loop below computes the remaining 1 to 3 samples. */ + while (blkCnt > 0U) + { + /* C = A * 8388608 */ + /* Convert from float to q23 and then store the results in the destination buffer */ + inV = vld1q_f32(pIn); + + cvt = vcvtq_n_s32_f32(inV, 23); + + /* saturate */ + cvt = vminq_s32(cvt, vdupq_n_s32(0x007fffff)); + cvt = vmaxq_s32(cvt, vdupq_n_s32(0xff800000)); + + vst1q_s32(pDst, cvt); + pDst += 4; + pIn += 4; + + /* Decrement the loop counter */ + blkCnt--; + } + + /* If the blockSize is not a multiple of 4, compute any remaining output samples here. + ** No loop unrolling is used. */ + blkCnt = blockSize & 3; + + while (blkCnt > 0U) + { + /* C = A * 8388608 */ + /* Convert from float to q23 and then store the results in the destination buffer */ + *pDst++ = (q23_t) __SSAT((q31_t) (*pIn++ * 8388608.0f), 24); + + /* Decrement the loop counter */ + blkCnt--; + } +} +#else +void arm_float_to_q23(const float32_t * pSrc, q23_t * pDst, uint32_t blockSize) +{ + uint32_t blkCnt; /* Loop counter */ + const float32_t *pIn = pSrc; /* Source pointer */ + + /* Loop unrolling: Compute 4 outputs at a time */ + blkCnt = blockSize >> 2U; + + while (blkCnt > 0U) + { + /* C = A * 8388608 */ + /* convert from float to Q23 and store result in destination buffer */ + + *pDst++ = (q23_t) __SSAT((q31_t) (*pIn++ * 8388608.0f), 24); + *pDst++ = (q23_t) __SSAT((q31_t) (*pIn++ * 8388608.0f), 24); + *pDst++ = (q23_t) __SSAT((q31_t) (*pIn++ * 8388608.0f), 24); + *pDst++ = (q23_t) __SSAT((q31_t) (*pIn++ * 8388608.0f), 24); + + /* Decrement loop counter */ + blkCnt--; + } + + /* Loop unrolling: Compute remaining outputs */ + blkCnt = blockSize % 0x4U; + + while (blkCnt > 0U) + { + /* C = A * 8388608 */ + /* Convert from float to q23 and then store the results in the destination buffer */ + *pDst++ = (q23_t) __SSAT((q31_t) (*pIn++ * 8388608.0f), 24); + + /* Decrement loop counter */ + blkCnt--; + } + +} +#endif /* #if defined(ARM_MATH_NEON_EXPERIMENTAL) */ diff --git a/src/arm_float_to_q23.h b/src/arm_float_to_q23.h new file mode 100644 index 0000000..6a77ea8 --- /dev/null +++ b/src/arm_float_to_q23.h @@ -0,0 +1,22 @@ +#pragma once + +#include "arm_math_types.h" + +typedef int32_t q23_t; + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * @brief Converts the elements of the floating-point vector to Q23 vector. + * @param[in] pSrc points to the floating-point input vector + * @param[out] pDst points to the Q23 output vector + * @param[in] blockSize length of the input vector + */ +void arm_float_to_q23(const float32_t * pSrc, q23_t * pDst, uint32_t blockSize); + +#ifdef __cplusplus +} +#endif diff --git a/src/minidexed.cpp b/src/minidexed.cpp index 1cca446..cbed9f9 100644 --- a/src/minidexed.cpp +++ b/src/minidexed.cpp @@ -29,6 +29,7 @@ #include #include #include +#include "arm_float_to_q23.h" const char WLANFirmwarePath[] = "SD:firmware/"; const char WLANConfigFile[] = "SD:wpa_supplicant.conf"; @@ -359,7 +360,7 @@ bool CMiniDexed::Initialize (void) return false; } - m_pSoundDevice->SetWriteFormat (SoundFormatSigned16, Channels); + m_pSoundDevice->SetWriteFormat (SoundFormatSigned24_32, Channels); m_nQueueSizeFrames = m_pSoundDevice->GetQueueSizeFrames (); @@ -1260,8 +1261,8 @@ void CMiniDexed::ProcessSound (void) m_pTG[0]->getSamples (SampleBuffer, nFrames); // Convert single float array (mono) to int16 array - int16_t tmp_int[nFrames]; - arm_float_to_q15(SampleBuffer,tmp_int,nFrames); + int32_t tmp_int[nFrames]; + arm_float_to_q23(SampleBuffer,tmp_int,nFrames); if (m_pSoundDevice->Write (tmp_int, sizeof(tmp_int)) != (int) sizeof(tmp_int)) { @@ -1328,7 +1329,7 @@ void CMiniDexed::ProcessSound (void) // Note: one TG per audio channel; output=mono; no processing. const int Channels = 8; // One TG per channel float32_t tmp_float[nFrames*Channels]; - int16_t tmp_int[nFrames*Channels]; + int32_t tmp_int[nFrames*Channels]; if(nMasterVolume > 0.0) { @@ -1350,11 +1351,11 @@ void CMiniDexed::ProcessSound (void) } } } - arm_float_to_q15(tmp_float,tmp_int,nFrames*Channels); + arm_float_to_q23(tmp_float,tmp_int,nFrames*Channels); } else { - arm_fill_q15(0, tmp_int, nFrames*Channels); + arm_fill_q31(0, tmp_int, nFrames*Channels); } // Prevent PCM510x analog mute from kicking in @@ -1378,7 +1379,7 @@ void CMiniDexed::ProcessSound (void) // BEGIN TG mixing float32_t tmp_float[nFrames*2]; - int16_t tmp_int[nFrames*2]; + int32_t tmp_int[nFrames*2]; if(nMasterVolume > 0.0) { @@ -1444,11 +1445,11 @@ void CMiniDexed::ProcessSound (void) tmp_float[(i*2)+1]=SampleBuffer[indexR][i]; } } - arm_float_to_q15(tmp_float,tmp_int,nFrames*2); + arm_float_to_q23(tmp_float,tmp_int,nFrames*2); } else { - arm_fill_q15(0, tmp_int, nFrames * 2); + arm_fill_q31(0, tmp_int, nFrames * 2); } // Prevent PCM510x analog mute from kicking in From 23a3730d5099c7e592d302820e043fa8f78fb873 Mon Sep 17 00:00:00 2001 From: probonopd Date: Tue, 22 Apr 2025 19:03:05 +0200 Subject: [PATCH 2/4] NetworkSyslogEnabled and minor network related fixes (#876) Add `NetworkSyslogEnabled=1` to `minidexed.ini`, increase vebosity, add `syslogserver.py` --- src/config.cpp | 2 +- src/mididevice.cpp | 1 + src/minidexed.cpp | 9 +++++++ src/minidexed.ini | 1 + src/net/mdnspublisher.cpp | 6 +++++ submod.sh | 8 +++--- syslogserver.py | 57 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 79 insertions(+), 5 deletions(-) create mode 100644 syslogserver.py diff --git a/src/config.cpp b/src/config.cpp index 672d7cc..00d4d2d 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -209,7 +209,7 @@ void CConfig::Load (void) m_INetworkIPAddress = m_Properties.GetIPAddress("NetworkIPAddress") != 0; m_INetworkSubnetMask = m_Properties.GetIPAddress("NetworkSubnetMask") != 0; m_INetworkDefaultGateway = m_Properties.GetIPAddress("NetworkDefaultGateway") != 0; - m_bSyslogEnabled = m_Properties.GetNumber ("SyslogEnabled", 0) != 0; + m_bSyslogEnabled = m_Properties.GetNumber ("NetworkSyslogEnabled", 0) != 0; m_INetworkDNSServer = m_Properties.GetIPAddress("NetworkDNSServer") != 0; const u8 *pSyslogServerIP = m_Properties.GetIPAddress ("NetworkSyslogServerIPAddress"); diff --git a/src/mididevice.cpp b/src/mididevice.cpp index e13709f..c5e23ae 100644 --- a/src/mididevice.cpp +++ b/src/mididevice.cpp @@ -265,6 +265,7 @@ void CMIDIDevice::MIDIMessageHandler (const u8 *pMessage, size_t nLength, unsign else { // Ignore any other CC messages at this time + LOGNOTE("Ignoring CC %d (%d) on Performance Select Channel %d\n", pMessage[1], pMessage[2], nPerfCh); } } } diff --git a/src/minidexed.cpp b/src/minidexed.cpp index cbed9f9..7664e99 100644 --- a/src/minidexed.cpp +++ b/src/minidexed.cpp @@ -2307,6 +2307,7 @@ void CMiniDexed::UpdateNetwork() if (m_pConfig->GetSyslogEnabled()) { + LOGNOTE ("Syslog server is enabled in configuration"); CIPAddress ServerIP = m_pConfig->GetNetworkSyslogServerIPAddress(); if (ServerIP.IsSet () && !ServerIP.IsNull ()) { @@ -2318,6 +2319,14 @@ void CMiniDexed::UpdateNetwork() new CSysLogDaemon (m_pNet, ServerIP, usServerPort); } + else + { + LOGNOTE ("Syslog server IP not set"); + } + } + else + { + LOGNOTE ("Syslog server is not enabled in configuration"); } m_bNetworkReady = true; } diff --git a/src/minidexed.ini b/src/minidexed.ini index 2291f4f..d7de8ce 100644 --- a/src/minidexed.ini +++ b/src/minidexed.ini @@ -161,6 +161,7 @@ NetworkIPAddress=0 NetworkSubnetMask=0 NetworkDefaultGateway=0 NetworkDNSServer=0 +NetworkSyslogEnabled=1 NetworkSyslogServerIPAddress=0 # Performance diff --git a/src/net/mdnspublisher.cpp b/src/net/mdnspublisher.cpp index 23052db..fbeb549 100644 --- a/src/net/mdnspublisher.cpp +++ b/src/net/mdnspublisher.cpp @@ -117,10 +117,13 @@ boolean CmDNSPublisher::UnpublishService (const char *pServiceName) return FALSE; } LOGDBG ("Unpublish service %s", (const char *) pService->ServiceName); + SendResponse (pService, FALSE); + /* if (!SendResponse (pService, TRUE)) { LOGWARN ("Send failed"); } + */ for (unsigned i = 0; i < pService->nTextRecords; i++) { delete pService->ppText[i]; @@ -172,10 +175,13 @@ void CmDNSPublisher::Run (void) TService *pService = static_cast (CPtrList::GetPtr (pElement)); assert (pService); + SendResponse (pService, FALSE); + /* if (!SendResponse (pService, FALSE)) { LOGWARN ("Send failed"); } + */ pElement = m_ServiceList.GetNext (pElement); } m_Mutex.Release (); diff --git a/submod.sh b/submod.sh index 6685bef..f9d3251 100755 --- a/submod.sh +++ b/submod.sh @@ -2,13 +2,13 @@ set -ex # Update top-level modules as a baseline -git submodule update --init --recursive +git submodule update --init --recursive -f # Use fixed master branch of circle-stdlib then re-update cd circle-stdlib/ git reset --hard -git checkout 1111eee # Matches Circle Step49 -git submodule update --init --recursive +git checkout 1111eee -f # Matches Circle Step49 +git submodule update --init --recursive -f cd - # Optional update submodules explicitly @@ -23,5 +23,5 @@ cd - # Use fixed master branch of Synth_Dexed cd Synth_Dexed/ git reset --hard -git checkout c9f5274 +git checkout c9f5274 -f cd - diff --git a/syslogserver.py b/syslogserver.py new file mode 100644 index 0000000..c07c1ea --- /dev/null +++ b/syslogserver.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +""" +Syslog server to receive and display syslog messages from MiniDexed. +""" + +import socket +import time +import threading + +class SyslogServer: + def __init__(self, host='0.0.0.0', port=8514): + self.host = host + self.port = port + self.server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + self.server.bind((self.host, self.port)) + self.start_time = None + self.running = True + + def start(self): + ip_address = socket.gethostbyname(socket.gethostname()) + print(f"Syslog server listening on {ip_address}:{self.port}") + input_thread = threading.Thread(target=self.wait_for_input) + input_thread.daemon = True + input_thread.start() + while self.running: + try: + data, address = self.server.recvfrom(1024) + self.handle_message(data) + except KeyboardInterrupt: + self.running = False + + def handle_message(self, data): + message = data[2:].decode('utf-8').strip() + + if self.start_time is None: + self.start_time = time.time() + relative_time = "0:00:00.000" + else: + elapsed_time = time.time() - self.start_time + hours = int(elapsed_time // 3600) + minutes = int((elapsed_time % 3600) // 60) + seconds = int(elapsed_time % 60) + milliseconds = int((elapsed_time % 1) * 1000) + relative_time = f"{hours:02d}:{minutes:02d}:{seconds:02d}.{milliseconds:03d}" + + print(f"{relative_time} {message}") + + def wait_for_input(self): + input("Press any key to exit...") + self.running = False + +if __name__ == "__main__": + server = SyslogServer() + server.start() + print("Syslog server stopped.") \ No newline at end of file From c0d73e362976f1d6d3363be23e03d8e49134f585 Mon Sep 17 00:00:00 2001 From: probonopd Date: Tue, 22 Apr 2025 19:05:46 +0200 Subject: [PATCH 3/4] NetworkSyslogEnabled=0 by default [ci skip] --- src/minidexed.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/minidexed.ini b/src/minidexed.ini index d7de8ce..7d0fd31 100644 --- a/src/minidexed.ini +++ b/src/minidexed.ini @@ -161,7 +161,7 @@ NetworkIPAddress=0 NetworkSubnetMask=0 NetworkDefaultGateway=0 NetworkDNSServer=0 -NetworkSyslogEnabled=1 +NetworkSyslogEnabled=0 NetworkSyslogServerIPAddress=0 # Performance From 22a7d54251b10d7311f730ae7a7417915ef58e69 Mon Sep 17 00:00:00 2001 From: probonopd Date: Tue, 22 Apr 2025 19:51:08 +0200 Subject: [PATCH 4/4] Put all files into 64bit artifact (#873) Closes https://github.com/probonopd/MiniDexed/discussions/869#discussioncomment-12905515 --- .github/workflows/build.yml | 67 +++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 29 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a17d88d..5248d4b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,9 +1,8 @@ -# Build 32-bit and 64-bit separately - name: Build env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GIT_INFO: "" on: push: @@ -19,14 +18,16 @@ jobs: artifact-path: ${{ steps.upload64.outputs.artifact-path }} steps: - uses: actions/checkout@v2 + - name: Compute Git Info for Artifact Name + run: echo "GIT_INFO=$(date +%Y-%m-%d)-$(git rev-parse --short HEAD)" >> $GITHUB_ENV - name: Get specific commits of git submodules run: sh -ex ./submod.sh - name: Create sdcard directory run: mkdir -p ./sdcard/ - name: Put git hash in startup message run: | - sed -i "s/Loading.../$(date +%Y%m%d)-$(git rev-parse --short HEAD)/g" src/userinterface.cpp - + sed -i "s/Loading.../${{ env.GIT_INFO }}/g" src/userinterface.cpp + # Install 64-bit toolchain (aarch64) - name: Install 64-bit toolchain run: | @@ -65,15 +66,30 @@ jobs: cd - cp -r ./circle-stdlib/libs/circle/boot/* sdcard rm -rf sdcard/config*.txt sdcard/README sdcard/Makefile sdcard/armstub sdcard/COPYING.linux - cp ./src/config.txt ./src/minidexed.ini ./src/*img ./src/performance.ini sdcard/ + cp ./src/config.txt ./src/minidexed.ini ./src/performance.ini sdcard/ cp ./getsysex.sh sdcard/ echo "usbspeed=full" > sdcard/cmdline.txt - + # Performances + git clone https://github.com/Banana71/Soundplantage --depth 1 # depth 1 means only the latest commit + cp -r ./Soundplantage/performance ./Soundplantage/*.pdf ./sdcard/ + # Hardware configuration + cd hwconfig + sh -ex ./customize.sh + cd - + mkdir -p ./sdcard/hardware/ + cp -r ./hwconfig/minidexed_* ./sdcard/minidexed.ini ./sdcard/hardware/ + # WLAN firmware + mkdir -p sdcard/firmware + cp circle-stdlib/libs/circle/addon/wlan/sample/hello_wlan/wpa_supplicant.conf sdcard/ + cd sdcard/firmware + make -f ../../circle-stdlib/libs/circle/addon/wlan/firmware/Makefile + cd - + - name: Upload 64-bit artifacts id: upload64 uses: actions/upload-artifact@v4 with: - name: build64-artifacts + name: MiniDexed_${{ github.run_number }}_${{ env.GIT_INFO }}_64bit path: sdcard/* build32: @@ -83,14 +99,16 @@ jobs: artifact-path: ${{ steps.upload32.outputs.artifact-path }} steps: - uses: actions/checkout@v2 + - name: Compute Git Info for Artifact Name + run: echo "GIT_INFO=$(date +%Y-%m-%d)-$(git rev-parse --short HEAD)" >> $GITHUB_ENV - name: Get specific commits of git submodules run: sh -ex ./submod.sh - name: Create sdcard directory run: mkdir -p ./sdcard/ - name: Put git hash in startup message run: | - sed -i "s/Loading.../$(date +%Y%m%d)-$(git rev-parse --short HEAD)/g" src/userinterface.cpp - + sed -i "s/Loading.../${{ env.GIT_INFO }}/g" src/userinterface.cpp + # Install 32-bit toolchain (arm-none-eabi) - name: Install 32-bit toolchain run: | @@ -116,7 +134,7 @@ jobs: id: upload32 uses: actions/upload-artifact@v4 with: - name: build32-artifacts + name: MiniDexed_${{ github.run_number }}_${{ env.GIT_INFO }}_32bit path: sdcard/* combine: @@ -124,32 +142,23 @@ jobs: runs-on: ubuntu-22.04 needs: [ build64, build32 ] steps: - - name: Download 64-bit artifacts - uses: actions/download-artifact@v4 - with: - name: build64-artifacts - path: combined - - name: Download 32-bit artifacts + - name: Download artifacts uses: actions/download-artifact@v4 with: - name: build32-artifacts + pattern: MiniDexed_* + merge-multiple: true path: combined - name: Create combined ZIP file run: | cd combined - zip -r ../MiniDexed_${GITHUB_RUN_NUMBER}_$(date +%Y-%m-%d)-$(git rev-parse --short HEAD).zip . + zip -r ../MiniDexed_${{ github.run_number }}_${{ env.GIT_INFO }}.zip . cd .. - - name: Upload combined ZIP artifact - uses: actions/upload-artifact@v4 - with: - name: combined-artifact - path: MiniDexed_${GITHUB_RUN_NUMBER}_$(date +%Y-%m-%d)-$(git rev-parse --short HEAD).zip - name: Upload to GitHub Releases (only when building from main branch) if: ${{ github.ref == 'refs/heads/main' }} run: | - set -ex - export UPLOADTOOL_ISPRERELEASE=true - export UPLOADTOOL_PR_BODY="This is a continuous build. Feedback is appreciated." - export UPLOADTOOL_BODY="This is a continuous build. Feedback is appreciated." - wget -c https://github.com/probonopd/uploadtool/raw/master/upload.sh - bash ./upload.sh ./MiniDexed*.zip + set -ex + export UPLOADTOOL_ISPRERELEASE=true + export UPLOADTOOL_PR_BODY="This is a continuous build. Feedback is appreciated." + export UPLOADTOOL_BODY="This is a continuous build. Feedback is appreciated." + wget -c https://github.com/probonopd/uploadtool/raw/master/upload.sh + bash ./upload.sh ./MiniDexed*.zip