From f087ac4c8247b1d00dc5d46b9b26cd0b97807ffc Mon Sep 17 00:00:00 2001 From: Eric Coissac Date: Tue, 16 Sep 2025 20:53:23 +0200 Subject: [PATCH] On range tout pour recommencer en rust --- .gitignore | 4 + C/include/soxr-lsr.h | 78 - C/include/soxr.h | 344 - C/lib/libsoxr-lsr.a | Bin 5992 -> 0 bytes C/lib/libsoxr.a | Bin 188200 -> 0 bytes C/lib/pkgconfig/soxr-lsr.pc | 5 - C/lib/pkgconfig/soxr.pc | 5 - C/share/doc/libsoxr/LICENCE | 23 - C/share/doc/libsoxr/NEWS | 46 - C/share/doc/libsoxr/README | 53 - C/share/doc/libsoxr/examples/1-single-block.c | 50 - C/share/doc/libsoxr/examples/1a-lsr.c | 40 - C/share/doc/libsoxr/examples/2-stream.C | 78 - .../doc/libsoxr/examples/3-options-input-fn.c | 114 - .../doc/libsoxr/examples/4-split-channels.c | 161 - .../doc/libsoxr/examples/5-variable-rate.c | 93 - C/share/doc/libsoxr/examples/README | 20 - .../doc/libsoxr/examples/examples-common.h | 47 - C/src/soxr-0.1.3/AUTHORS | 1 - C/src/soxr-0.1.3/CMakeLists.txt | 335 - C/src/soxr-0.1.3/COPYING.LGPL | 502 -- C/src/soxr-0.1.3/INSTALL | 183 - C/src/soxr-0.1.3/LICENCE | 23 - C/src/soxr-0.1.3/NEWS | 46 - C/src/soxr-0.1.3/README | 53 - C/src/soxr-0.1.3/TODO | 3 - .../soxr-0.1.3/cmake/Modules/FindCFlags.cmake | 35 - .../cmake/Modules/FindLibAVCodec.cmake | 23 - .../cmake/Modules/FindLibAVUtil.cmake | 23 - .../soxr-0.1.3/cmake/Modules/FindSIMD32.cmake | 54 - .../soxr-0.1.3/cmake/Modules/FindSIMD64.cmake | 29 - .../cmake/Modules/SetSystemProcessor.cmake | 37 - C/src/soxr-0.1.3/deinstall.cmake.in | 25 - C/src/soxr-0.1.3/examples/1-single-block.c | 50 - C/src/soxr-0.1.3/examples/1a-lsr.c | 40 - C/src/soxr-0.1.3/examples/2-stream.C | 78 - .../soxr-0.1.3/examples/3-options-input-fn.c | 114 - C/src/soxr-0.1.3/examples/4-split-channels.c | 161 - C/src/soxr-0.1.3/examples/5-variable-rate.c | 93 - C/src/soxr-0.1.3/examples/CMakeLists.txt | 36 - C/src/soxr-0.1.3/examples/README | 20 - C/src/soxr-0.1.3/examples/examples-common.h | 47 - C/src/soxr-0.1.3/go | 21 - C/src/soxr-0.1.3/go.bat | 27 - C/src/soxr-0.1.3/inst-check | 25 - C/src/soxr-0.1.3/inst-check-soxr | 52 - C/src/soxr-0.1.3/inst-check-soxr-lsr | 1 - C/src/soxr-0.1.3/msvc/README | 22 - C/src/soxr-0.1.3/msvc/example1.vcproj | 82 - C/src/soxr-0.1.3/msvc/libsoxr.sln | 29 - C/src/soxr-0.1.3/msvc/libsoxr.vcproj | 97 - C/src/soxr-0.1.3/msvc/soxr-config.h | 30 - C/src/soxr-0.1.3/multi-arch | 31 - C/src/soxr-0.1.3/soxr-config.h.in | 27 - C/src/soxr-0.1.3/src/CMakeLists.txt | 129 - C/src/soxr-0.1.3/src/aliases.h | 39 - C/src/soxr-0.1.3/src/avfft32.c | 33 - C/src/soxr-0.1.3/src/avfft32s.c | 32 - C/src/soxr-0.1.3/src/ccrw2.h | 75 - C/src/soxr-0.1.3/src/cr-core.c | 314 - C/src/soxr-0.1.3/src/cr.c | 588 -- C/src/soxr-0.1.3/src/cr.h | 178 - C/src/soxr-0.1.3/src/cr32.c | 8 - C/src/soxr-0.1.3/src/cr32s.c | 8 - C/src/soxr-0.1.3/src/cr64.c | 8 - C/src/soxr-0.1.3/src/cr64s.c | 8 - C/src/soxr-0.1.3/src/data-io.c | 223 - C/src/soxr-0.1.3/src/data-io.h | 39 - C/src/soxr-0.1.3/src/dbesi0.c | 149 - C/src/soxr-0.1.3/src/dev32s.h | 54 - C/src/soxr-0.1.3/src/dev64s.h | 42 - C/src/soxr-0.1.3/src/fft4g.c | 1346 ---- C/src/soxr-0.1.3/src/fft4g.h | 23 - C/src/soxr-0.1.3/src/fft4g32.c | 36 - C/src/soxr-0.1.3/src/fft4g32s.c | 31 - C/src/soxr-0.1.3/src/fft4g64.c | 35 - C/src/soxr-0.1.3/src/fft4g_cache.h | 92 - C/src/soxr-0.1.3/src/fifo.h | 125 - C/src/soxr-0.1.3/src/filter.c | 277 - C/src/soxr-0.1.3/src/filter.h | 44 - C/src/soxr-0.1.3/src/half-coefs.h | 75 - C/src/soxr-0.1.3/src/half-fir.h | 61 - C/src/soxr-0.1.3/src/internal.h | 84 - C/src/soxr-0.1.3/src/math-wrap.h | 31 - C/src/soxr-0.1.3/src/pffft-avx.h | 40 - C/src/soxr-0.1.3/src/pffft-wrap.c | 110 - C/src/soxr-0.1.3/src/pffft.c | 1946 ------ C/src/soxr-0.1.3/src/pffft.h | 197 - C/src/soxr-0.1.3/src/pffft32.c | 39 - C/src/soxr-0.1.3/src/pffft32s.c | 34 - C/src/soxr-0.1.3/src/pffft64s.c | 34 - C/src/soxr-0.1.3/src/poly-fir.h | 150 - C/src/soxr-0.1.3/src/poly-fir0.h | 56 - C/src/soxr-0.1.3/src/rdft.h | 31 - C/src/soxr-0.1.3/src/rdft_t.h | 24 - C/src/soxr-0.1.3/src/rint-clip.h | 158 - C/src/soxr-0.1.3/src/rint.h | 102 - C/src/soxr-0.1.3/src/samplerate.h | 1 - C/src/soxr-0.1.3/src/soxr-lsr.c | 198 - C/src/soxr-0.1.3/src/soxr-lsr.h | 78 - C/src/soxr-0.1.3/src/soxr-lsr.pc.in | 5 - C/src/soxr-0.1.3/src/soxr.c | 842 --- C/src/soxr-0.1.3/src/soxr.h | 344 - C/src/soxr-0.1.3/src/soxr.pc.in | 5 - C/src/soxr-0.1.3/src/std-types.h | 48 - C/src/soxr-0.1.3/src/util-simd.c | 89 - C/src/soxr-0.1.3/src/util32s.c | 8 - C/src/soxr-0.1.3/src/util32s.h | 23 - C/src/soxr-0.1.3/src/util64s.c | 8 - C/src/soxr-0.1.3/src/util64s.h | 23 - C/src/soxr-0.1.3/src/vr-coefs.c | 115 - C/src/soxr-0.1.3/src/vr-coefs.h | 94 - C/src/soxr-0.1.3/src/vr32.c | 651 -- C/src/soxr-0.1.3/tests/1-delay-clear.c | 64 - C/src/soxr-0.1.3/tests/CMakeLists.txt | 62 - C/src/soxr-0.1.3/tests/README | 1 - C/src/soxr-0.1.3/tests/bandwidth-test | 41 - C/src/soxr-0.1.3/tests/cmp-test.cmake | 30 - C/src/soxr-0.1.3/tests/eg-test | 48 - C/src/soxr-0.1.3/tests/io-test | 65 - C/src/soxr-0.1.3/tests/large-ratio-test | 22 - C/src/soxr-0.1.3/tests/phase-test | 39 - C/src/soxr-0.1.3/tests/q-test | 73 - C/src/soxr-0.1.3/tests/scripts | 14 - C/src/soxr-0.1.3/tests/throughput-test | 11 - C/src/soxr-0.1.3/tests/throughput-test.bat | 5 - C/src/soxr-0.1.3/tests/throughput.c | 141 - C/src/soxr-0.1.3/tests/time-test | 36 - C/src/soxr-0.1.3/tests/vector-cmp.c | 56 - C/src/soxr-0.1.3/tests/vector-gen.c | 61 - Makefile | 51 - all.txt | 1327 ---- cmd/pmomusic/main.go | 36 - fileutils/iswritable.go | 27 - go.mod | 37 - go.sum | 141 - netutils/ip_detect.go | 17 - netutils/list_all_ip.go | 49 - pmoapp/web.go | 35 - pmoapp/web/.gitignore | 24 - pmoapp/web/README.md | 69 - pmoapp/web/eslint.config.js | 23 - pmoapp/web/index.html | 11 - pmoapp/web/package-lock.json | 5869 ----------------- pmoapp/web/package.json | 40 - pmoapp/web/postcss.config.mjs | 6 - pmoapp/web/public/vite.svg | 1 - pmoapp/web/src/App.css | 207 - pmoapp/web/src/App.tsx | 73 - pmoapp/web/src/Covers.tsx | 46 - pmoapp/web/src/Logs.tsx | 65 - pmoapp/web/src/assets/react.svg | 1 - pmoapp/web/src/custom.d.ts | 20 - pmoapp/web/src/index.css | 68 - pmoapp/web/src/main.tsx | 10 - pmoapp/web/src/vite-env.d.ts | 1 - pmoapp/web/tailwind.config.js | 5 - pmoapp/web/tsconfig.app.json | 27 - pmoapp/web/tsconfig.json | 7 - pmoapp/web/tsconfig.node.json | 25 - pmoapp/web/vite.config.ts | 7 - pmoconfig/config.go | 410 -- pmoconfig/pmomusic.yaml | 11 - pmocover/cache.go | 209 - pmocover/db.go | 124 - pmocover/handler.go | 62 - pmocover/pmocover.go | 16 - pmocover/webp.go | 87 - pmodidl/didilite.go | 281 - pmodidl/markdown.go | 129 - pmodidl/model.go | 67 - pmodidl/parser.go | 26 - pmolog/index.html | 523 -- pmolog/prettyxml.go | 24 - pmolog/webloger.go | 197 - pmosoxr/concurency_test.go | 90 - pmosoxr/quality.go | 34 - pmosoxr/soxr.go | 124 - pmosoxr_test/pmo_soxr_test.go | 94 - pmosoxr_test/pmosoxr_test.go | 69 - pmostream/audio.go | 60 - pmostream/buffer.go | 139 - pmostream/conversion.go | 88 - pmostream/core.go | 271 - pmostream/fork.go | 208 - pmostream/fork_eq_test.go | 47 - pmostream/parameq.go | 93 - pmostream/streamer.go | 150 - pmostream_test/pmostream_test.go | 131 - pmoupnp/debug_index.go | 35 - pmoupnp/dev_set.go | 36 - pmoupnp/device.go | 160 - pmoupnp/deviceinstance.go | 179 - .../mediarenderer/AVTransport/ac_Play.go | 23 - .../AVTransport/ac_SetAVTransportURI.go | 30 - .../mediarenderer/AVTransport/ac_Stop.go | 16 - .../AVTransport/sv_AVTransportURI.go | 10 - .../AVTransport/sv_AVTransportURIMetaData.go | 25 - .../AVTransport/sv_A_ARG_TYPE_InstanceID.go | 10 - .../AVTransport/sv_A_ARG_TYPE_PlaySpeed.go | 10 - .../AVTransport/sv_CurrentTrackDuration.go | 10 - .../mediarenderer/AVTransport/sv_SeekMode.go | 10 - .../AVTransport/sv_TransportPlaySpeed.go | 11 - .../AVTransport/sv_TransportState.go | 22 - .../AVTransport/sv_TransportStatus.go | 17 - .../AVTransport/svc_avtransport.go | 23 - .../ac_GetCurrentConnectionIDs.go | 16 - .../ac_GetCurrentConnectionInfo.go | 64 - .../ConnectionManager/ac_GetProtocolInfo.go | 23 - .../ConnectionManager/sv_AVTransportID.go | 10 - .../sv_A_ARG_TYPE_AVTransportID.go | 10 - .../sv_A_ARG_TYPE_ConnectionID.go | 10 - .../sv_A_ARG_TYPE_ConnectionManager.go | 10 - .../sv_A_ARG_TYPE_ConnectionStatus.go | 17 - .../sv_A_ARG_TYPE_Direction.go | 11 - .../sv_A_ARG_TYPE_ProtocolInfo.go | 10 - .../ConnectionManager/sv_A_ARG_TYPE_RcsID.go | 10 - .../ConnectionManager/sv_ConnectionID.go | 10 - .../sv_CurrentConnectionIDs.go | 10 - .../ConnectionManager/sv_Direction.go | 11 - .../ConnectionManager/sv_PeerConnectionID.go | 10 - .../sv_PeerConnectionManager.go | 10 - .../ConnectionManager/sv_RcsID.go | 10 - .../ConnectionManager/sv_SinkProtocolInfo.go | 10 - .../sv_SourceProtocolInfo.go | 10 - .../ConnectionManager/sv_Status.go | 17 - .../svc_connectionmanager.go | 32 - .../RenderingControl/sv_Channel.go | 11 - .../RenderingControl/sv_InstanceID.go | 10 - .../mediarenderer/RenderingControl/sv_Mute.go | 12 - .../RenderingControl/sv_SourceProtocolInfo.go | 1 - .../RenderingControl/sv_Volume.go | 15 - .../RenderingControl/svc_renderingcontrol.go | 14 - .../devices/mediarenderer/mr_fake_renderer.go | 18 - pmoupnp/devices/services/actions/action.go | 37 - .../services/actions/actioninstance.go | 32 - .../services/actions/actioninstanceset.go | 32 - pmoupnp/devices/services/actions/actionset.go | 25 - pmoupnp/devices/services/actions/argument.go | 100 - .../devices/services/actions/argumentset.go | 32 - .../statevariables/statevalueinstance.go | 402 -- .../statevariables/statevalueinstanceset.go | 36 - .../services/statevariables/statevariable.go | 423 -- .../statevariable_TransferStatus.go | 17 - .../statevariables/statevariable_arithm.go | 39 - .../statevariables/statevariable_cast.go | 29 - .../statevariables/statevariable_cmp.go | 13 - .../statevariable_typechecking.go | 158 - .../statevariables/statevariableset.go | 25 - .../services/statevariables/statevartype.go | 194 - .../statevariables/statevartype_arithm.go | 73 - .../statevariables/statevartype_cast.go | 153 - .../statevariables/statevartype_cmp.go | 205 - .../statevartype_typechecking.go | 171 - .../services/statevariables/utils_binary.go | 62 - .../services/statevariables/utils_bool.go | 61 - .../services/statevariables/utils_float.go | 95 - .../services/statevariables/utils_int.go | 143 - .../statevariables/utils_numeric_operandes.go | 32 - .../services/statevariables/utils_string.go | 37 - .../services/statevariables/utils_time.go | 104 - .../services/statevariables/utils_uint.go | 100 - .../services/statevariables/utils_uri.go | 25 - .../services/statevariables/utils_uuid.go | 32 - .../services/statevariables/valuerange.go | 61 - pmoupnp/events.go | 5 - pmoupnp/interface.go | 5 - pmoupnp/objectstore/object.go | 69 - pmoupnp/objectstore/objectset.go | 40 - pmoupnp/server.go | 204 - pmoupnp/service.go | 99 - pmoupnp/serviceinstance.go | 460 -- pmoupnp/serviceinstanceset.go | 36 - pmoupnp/serviceset.go | 25 - pmoupnp/srv_reg_devices.go | 44 - soap/buildsoap.go | 89 - soap/markdown.go | 69 - soap/parseSoap.go | 195 - ssdp/server.go | 243 - xx | 806 --- 280 files changed, 4 insertions(+), 32476 deletions(-) delete mode 100644 C/include/soxr-lsr.h delete mode 100644 C/include/soxr.h delete mode 100644 C/lib/libsoxr-lsr.a delete mode 100644 C/lib/libsoxr.a delete mode 100644 C/lib/pkgconfig/soxr-lsr.pc delete mode 100644 C/lib/pkgconfig/soxr.pc delete mode 100644 C/share/doc/libsoxr/LICENCE delete mode 100644 C/share/doc/libsoxr/NEWS delete mode 100644 C/share/doc/libsoxr/README delete mode 100644 C/share/doc/libsoxr/examples/1-single-block.c delete mode 100644 C/share/doc/libsoxr/examples/1a-lsr.c delete mode 100644 C/share/doc/libsoxr/examples/2-stream.C delete mode 100644 C/share/doc/libsoxr/examples/3-options-input-fn.c delete mode 100644 C/share/doc/libsoxr/examples/4-split-channels.c delete mode 100644 C/share/doc/libsoxr/examples/5-variable-rate.c delete mode 100644 C/share/doc/libsoxr/examples/README delete mode 100644 C/share/doc/libsoxr/examples/examples-common.h delete mode 100644 C/src/soxr-0.1.3/AUTHORS delete mode 100644 C/src/soxr-0.1.3/CMakeLists.txt delete mode 100644 C/src/soxr-0.1.3/COPYING.LGPL delete mode 100644 C/src/soxr-0.1.3/INSTALL delete mode 100644 C/src/soxr-0.1.3/LICENCE delete mode 100644 C/src/soxr-0.1.3/NEWS delete mode 100644 C/src/soxr-0.1.3/README delete mode 100644 C/src/soxr-0.1.3/TODO delete mode 100644 C/src/soxr-0.1.3/cmake/Modules/FindCFlags.cmake delete mode 100644 C/src/soxr-0.1.3/cmake/Modules/FindLibAVCodec.cmake delete mode 100644 C/src/soxr-0.1.3/cmake/Modules/FindLibAVUtil.cmake delete mode 100644 C/src/soxr-0.1.3/cmake/Modules/FindSIMD32.cmake delete mode 100644 C/src/soxr-0.1.3/cmake/Modules/FindSIMD64.cmake delete mode 100644 C/src/soxr-0.1.3/cmake/Modules/SetSystemProcessor.cmake delete mode 100644 C/src/soxr-0.1.3/deinstall.cmake.in delete mode 100644 C/src/soxr-0.1.3/examples/1-single-block.c delete mode 100644 C/src/soxr-0.1.3/examples/1a-lsr.c delete mode 100644 C/src/soxr-0.1.3/examples/2-stream.C delete mode 100644 C/src/soxr-0.1.3/examples/3-options-input-fn.c delete mode 100644 C/src/soxr-0.1.3/examples/4-split-channels.c delete mode 100644 C/src/soxr-0.1.3/examples/5-variable-rate.c delete mode 100644 C/src/soxr-0.1.3/examples/CMakeLists.txt delete mode 100644 C/src/soxr-0.1.3/examples/README delete mode 100644 C/src/soxr-0.1.3/examples/examples-common.h delete mode 100755 C/src/soxr-0.1.3/go delete mode 100644 C/src/soxr-0.1.3/go.bat delete mode 100755 C/src/soxr-0.1.3/inst-check delete mode 100755 C/src/soxr-0.1.3/inst-check-soxr delete mode 120000 C/src/soxr-0.1.3/inst-check-soxr-lsr delete mode 100644 C/src/soxr-0.1.3/msvc/README delete mode 100644 C/src/soxr-0.1.3/msvc/example1.vcproj delete mode 100644 C/src/soxr-0.1.3/msvc/libsoxr.sln delete mode 100644 C/src/soxr-0.1.3/msvc/libsoxr.vcproj delete mode 100644 C/src/soxr-0.1.3/msvc/soxr-config.h delete mode 100755 C/src/soxr-0.1.3/multi-arch delete mode 100644 C/src/soxr-0.1.3/soxr-config.h.in delete mode 100644 C/src/soxr-0.1.3/src/CMakeLists.txt delete mode 100644 C/src/soxr-0.1.3/src/aliases.h delete mode 100644 C/src/soxr-0.1.3/src/avfft32.c delete mode 100644 C/src/soxr-0.1.3/src/avfft32s.c delete mode 100644 C/src/soxr-0.1.3/src/ccrw2.h delete mode 100644 C/src/soxr-0.1.3/src/cr-core.c delete mode 100644 C/src/soxr-0.1.3/src/cr.c delete mode 100644 C/src/soxr-0.1.3/src/cr.h delete mode 100644 C/src/soxr-0.1.3/src/cr32.c delete mode 100644 C/src/soxr-0.1.3/src/cr32s.c delete mode 100644 C/src/soxr-0.1.3/src/cr64.c delete mode 100644 C/src/soxr-0.1.3/src/cr64s.c delete mode 100644 C/src/soxr-0.1.3/src/data-io.c delete mode 100644 C/src/soxr-0.1.3/src/data-io.h delete mode 100644 C/src/soxr-0.1.3/src/dbesi0.c delete mode 100644 C/src/soxr-0.1.3/src/dev32s.h delete mode 100644 C/src/soxr-0.1.3/src/dev64s.h delete mode 100644 C/src/soxr-0.1.3/src/fft4g.c delete mode 100644 C/src/soxr-0.1.3/src/fft4g.h delete mode 100644 C/src/soxr-0.1.3/src/fft4g32.c delete mode 100644 C/src/soxr-0.1.3/src/fft4g32s.c delete mode 100644 C/src/soxr-0.1.3/src/fft4g64.c delete mode 100644 C/src/soxr-0.1.3/src/fft4g_cache.h delete mode 100644 C/src/soxr-0.1.3/src/fifo.h delete mode 100644 C/src/soxr-0.1.3/src/filter.c delete mode 100644 C/src/soxr-0.1.3/src/filter.h delete mode 100644 C/src/soxr-0.1.3/src/half-coefs.h delete mode 100644 C/src/soxr-0.1.3/src/half-fir.h delete mode 100644 C/src/soxr-0.1.3/src/internal.h delete mode 100644 C/src/soxr-0.1.3/src/math-wrap.h delete mode 100644 C/src/soxr-0.1.3/src/pffft-avx.h delete mode 100644 C/src/soxr-0.1.3/src/pffft-wrap.c delete mode 100644 C/src/soxr-0.1.3/src/pffft.c delete mode 100644 C/src/soxr-0.1.3/src/pffft.h delete mode 100644 C/src/soxr-0.1.3/src/pffft32.c delete mode 100644 C/src/soxr-0.1.3/src/pffft32s.c delete mode 100644 C/src/soxr-0.1.3/src/pffft64s.c delete mode 100644 C/src/soxr-0.1.3/src/poly-fir.h delete mode 100644 C/src/soxr-0.1.3/src/poly-fir0.h delete mode 100644 C/src/soxr-0.1.3/src/rdft.h delete mode 100644 C/src/soxr-0.1.3/src/rdft_t.h delete mode 100644 C/src/soxr-0.1.3/src/rint-clip.h delete mode 100644 C/src/soxr-0.1.3/src/rint.h delete mode 100644 C/src/soxr-0.1.3/src/samplerate.h delete mode 100644 C/src/soxr-0.1.3/src/soxr-lsr.c delete mode 100644 C/src/soxr-0.1.3/src/soxr-lsr.h delete mode 100644 C/src/soxr-0.1.3/src/soxr-lsr.pc.in delete mode 100644 C/src/soxr-0.1.3/src/soxr.c delete mode 100644 C/src/soxr-0.1.3/src/soxr.h delete mode 100644 C/src/soxr-0.1.3/src/soxr.pc.in delete mode 100644 C/src/soxr-0.1.3/src/std-types.h delete mode 100644 C/src/soxr-0.1.3/src/util-simd.c delete mode 100644 C/src/soxr-0.1.3/src/util32s.c delete mode 100644 C/src/soxr-0.1.3/src/util32s.h delete mode 100644 C/src/soxr-0.1.3/src/util64s.c delete mode 100644 C/src/soxr-0.1.3/src/util64s.h delete mode 100644 C/src/soxr-0.1.3/src/vr-coefs.c delete mode 100644 C/src/soxr-0.1.3/src/vr-coefs.h delete mode 100644 C/src/soxr-0.1.3/src/vr32.c delete mode 100644 C/src/soxr-0.1.3/tests/1-delay-clear.c delete mode 100644 C/src/soxr-0.1.3/tests/CMakeLists.txt delete mode 100644 C/src/soxr-0.1.3/tests/README delete mode 100755 C/src/soxr-0.1.3/tests/bandwidth-test delete mode 100644 C/src/soxr-0.1.3/tests/cmp-test.cmake delete mode 100755 C/src/soxr-0.1.3/tests/eg-test delete mode 100755 C/src/soxr-0.1.3/tests/io-test delete mode 100755 C/src/soxr-0.1.3/tests/large-ratio-test delete mode 100755 C/src/soxr-0.1.3/tests/phase-test delete mode 100755 C/src/soxr-0.1.3/tests/q-test delete mode 100755 C/src/soxr-0.1.3/tests/scripts delete mode 100755 C/src/soxr-0.1.3/tests/throughput-test delete mode 100644 C/src/soxr-0.1.3/tests/throughput-test.bat delete mode 100644 C/src/soxr-0.1.3/tests/throughput.c delete mode 100755 C/src/soxr-0.1.3/tests/time-test delete mode 100644 C/src/soxr-0.1.3/tests/vector-cmp.c delete mode 100644 C/src/soxr-0.1.3/tests/vector-gen.c delete mode 100644 Makefile delete mode 100644 all.txt delete mode 100644 cmd/pmomusic/main.go delete mode 100644 fileutils/iswritable.go delete mode 100644 go.mod delete mode 100644 go.sum delete mode 100644 netutils/ip_detect.go delete mode 100644 netutils/list_all_ip.go delete mode 100644 pmoapp/web.go delete mode 100644 pmoapp/web/.gitignore delete mode 100644 pmoapp/web/README.md delete mode 100644 pmoapp/web/eslint.config.js delete mode 100644 pmoapp/web/index.html delete mode 100644 pmoapp/web/package-lock.json delete mode 100644 pmoapp/web/package.json delete mode 100644 pmoapp/web/postcss.config.mjs delete mode 100644 pmoapp/web/public/vite.svg delete mode 100644 pmoapp/web/src/App.css delete mode 100644 pmoapp/web/src/App.tsx delete mode 100644 pmoapp/web/src/Covers.tsx delete mode 100644 pmoapp/web/src/Logs.tsx delete mode 100644 pmoapp/web/src/assets/react.svg delete mode 100644 pmoapp/web/src/custom.d.ts delete mode 100644 pmoapp/web/src/index.css delete mode 100644 pmoapp/web/src/main.tsx delete mode 100644 pmoapp/web/src/vite-env.d.ts delete mode 100644 pmoapp/web/tailwind.config.js delete mode 100644 pmoapp/web/tsconfig.app.json delete mode 100644 pmoapp/web/tsconfig.json delete mode 100644 pmoapp/web/tsconfig.node.json delete mode 100644 pmoapp/web/vite.config.ts delete mode 100644 pmoconfig/config.go delete mode 100644 pmoconfig/pmomusic.yaml delete mode 100644 pmocover/cache.go delete mode 100644 pmocover/db.go delete mode 100644 pmocover/handler.go delete mode 100644 pmocover/pmocover.go delete mode 100644 pmocover/webp.go delete mode 100644 pmodidl/didilite.go delete mode 100644 pmodidl/markdown.go delete mode 100644 pmodidl/model.go delete mode 100644 pmodidl/parser.go delete mode 100644 pmolog/index.html delete mode 100644 pmolog/prettyxml.go delete mode 100644 pmolog/webloger.go delete mode 100644 pmosoxr/concurency_test.go delete mode 100644 pmosoxr/quality.go delete mode 100644 pmosoxr/soxr.go delete mode 100644 pmosoxr_test/pmo_soxr_test.go delete mode 100644 pmosoxr_test/pmosoxr_test.go delete mode 100644 pmostream/audio.go delete mode 100644 pmostream/buffer.go delete mode 100644 pmostream/conversion.go delete mode 100644 pmostream/core.go delete mode 100644 pmostream/fork.go delete mode 100644 pmostream/fork_eq_test.go delete mode 100644 pmostream/parameq.go delete mode 100644 pmostream/streamer.go delete mode 100644 pmostream_test/pmostream_test.go delete mode 100644 pmoupnp/debug_index.go delete mode 100644 pmoupnp/dev_set.go delete mode 100644 pmoupnp/device.go delete mode 100644 pmoupnp/deviceinstance.go delete mode 100644 pmoupnp/devices/mediarenderer/AVTransport/ac_Play.go delete mode 100644 pmoupnp/devices/mediarenderer/AVTransport/ac_SetAVTransportURI.go delete mode 100644 pmoupnp/devices/mediarenderer/AVTransport/ac_Stop.go delete mode 100644 pmoupnp/devices/mediarenderer/AVTransport/sv_AVTransportURI.go delete mode 100644 pmoupnp/devices/mediarenderer/AVTransport/sv_AVTransportURIMetaData.go delete mode 100644 pmoupnp/devices/mediarenderer/AVTransport/sv_A_ARG_TYPE_InstanceID.go delete mode 100644 pmoupnp/devices/mediarenderer/AVTransport/sv_A_ARG_TYPE_PlaySpeed.go delete mode 100644 pmoupnp/devices/mediarenderer/AVTransport/sv_CurrentTrackDuration.go delete mode 100644 pmoupnp/devices/mediarenderer/AVTransport/sv_SeekMode.go delete mode 100644 pmoupnp/devices/mediarenderer/AVTransport/sv_TransportPlaySpeed.go delete mode 100644 pmoupnp/devices/mediarenderer/AVTransport/sv_TransportState.go delete mode 100644 pmoupnp/devices/mediarenderer/AVTransport/sv_TransportStatus.go delete mode 100644 pmoupnp/devices/mediarenderer/AVTransport/svc_avtransport.go delete mode 100644 pmoupnp/devices/mediarenderer/ConnectionManager/ac_GetCurrentConnectionIDs.go delete mode 100644 pmoupnp/devices/mediarenderer/ConnectionManager/ac_GetCurrentConnectionInfo.go delete mode 100644 pmoupnp/devices/mediarenderer/ConnectionManager/ac_GetProtocolInfo.go delete mode 100644 pmoupnp/devices/mediarenderer/ConnectionManager/sv_AVTransportID.go delete mode 100644 pmoupnp/devices/mediarenderer/ConnectionManager/sv_A_ARG_TYPE_AVTransportID.go delete mode 100644 pmoupnp/devices/mediarenderer/ConnectionManager/sv_A_ARG_TYPE_ConnectionID.go delete mode 100644 pmoupnp/devices/mediarenderer/ConnectionManager/sv_A_ARG_TYPE_ConnectionManager.go delete mode 100644 pmoupnp/devices/mediarenderer/ConnectionManager/sv_A_ARG_TYPE_ConnectionStatus.go delete mode 100644 pmoupnp/devices/mediarenderer/ConnectionManager/sv_A_ARG_TYPE_Direction.go delete mode 100644 pmoupnp/devices/mediarenderer/ConnectionManager/sv_A_ARG_TYPE_ProtocolInfo.go delete mode 100644 pmoupnp/devices/mediarenderer/ConnectionManager/sv_A_ARG_TYPE_RcsID.go delete mode 100644 pmoupnp/devices/mediarenderer/ConnectionManager/sv_ConnectionID.go delete mode 100644 pmoupnp/devices/mediarenderer/ConnectionManager/sv_CurrentConnectionIDs.go delete mode 100644 pmoupnp/devices/mediarenderer/ConnectionManager/sv_Direction.go delete mode 100644 pmoupnp/devices/mediarenderer/ConnectionManager/sv_PeerConnectionID.go delete mode 100644 pmoupnp/devices/mediarenderer/ConnectionManager/sv_PeerConnectionManager.go delete mode 100644 pmoupnp/devices/mediarenderer/ConnectionManager/sv_RcsID.go delete mode 100644 pmoupnp/devices/mediarenderer/ConnectionManager/sv_SinkProtocolInfo.go delete mode 100644 pmoupnp/devices/mediarenderer/ConnectionManager/sv_SourceProtocolInfo.go delete mode 100644 pmoupnp/devices/mediarenderer/ConnectionManager/sv_Status.go delete mode 100644 pmoupnp/devices/mediarenderer/ConnectionManager/svc_connectionmanager.go delete mode 100644 pmoupnp/devices/mediarenderer/RenderingControl/sv_Channel.go delete mode 100644 pmoupnp/devices/mediarenderer/RenderingControl/sv_InstanceID.go delete mode 100644 pmoupnp/devices/mediarenderer/RenderingControl/sv_Mute.go delete mode 100644 pmoupnp/devices/mediarenderer/RenderingControl/sv_SourceProtocolInfo.go delete mode 100644 pmoupnp/devices/mediarenderer/RenderingControl/sv_Volume.go delete mode 100644 pmoupnp/devices/mediarenderer/RenderingControl/svc_renderingcontrol.go delete mode 100644 pmoupnp/devices/mediarenderer/mr_fake_renderer.go delete mode 100644 pmoupnp/devices/services/actions/action.go delete mode 100644 pmoupnp/devices/services/actions/actioninstance.go delete mode 100644 pmoupnp/devices/services/actions/actioninstanceset.go delete mode 100644 pmoupnp/devices/services/actions/actionset.go delete mode 100644 pmoupnp/devices/services/actions/argument.go delete mode 100644 pmoupnp/devices/services/actions/argumentset.go delete mode 100644 pmoupnp/devices/services/statevariables/statevalueinstance.go delete mode 100644 pmoupnp/devices/services/statevariables/statevalueinstanceset.go delete mode 100644 pmoupnp/devices/services/statevariables/statevariable.go delete mode 100644 pmoupnp/devices/services/statevariables/statevariable_TransferStatus.go delete mode 100644 pmoupnp/devices/services/statevariables/statevariable_arithm.go delete mode 100644 pmoupnp/devices/services/statevariables/statevariable_cast.go delete mode 100644 pmoupnp/devices/services/statevariables/statevariable_cmp.go delete mode 100644 pmoupnp/devices/services/statevariables/statevariable_typechecking.go delete mode 100644 pmoupnp/devices/services/statevariables/statevariableset.go delete mode 100644 pmoupnp/devices/services/statevariables/statevartype.go delete mode 100644 pmoupnp/devices/services/statevariables/statevartype_arithm.go delete mode 100644 pmoupnp/devices/services/statevariables/statevartype_cast.go delete mode 100644 pmoupnp/devices/services/statevariables/statevartype_cmp.go delete mode 100644 pmoupnp/devices/services/statevariables/statevartype_typechecking.go delete mode 100644 pmoupnp/devices/services/statevariables/utils_binary.go delete mode 100644 pmoupnp/devices/services/statevariables/utils_bool.go delete mode 100644 pmoupnp/devices/services/statevariables/utils_float.go delete mode 100644 pmoupnp/devices/services/statevariables/utils_int.go delete mode 100644 pmoupnp/devices/services/statevariables/utils_numeric_operandes.go delete mode 100644 pmoupnp/devices/services/statevariables/utils_string.go delete mode 100644 pmoupnp/devices/services/statevariables/utils_time.go delete mode 100644 pmoupnp/devices/services/statevariables/utils_uint.go delete mode 100644 pmoupnp/devices/services/statevariables/utils_uri.go delete mode 100644 pmoupnp/devices/services/statevariables/utils_uuid.go delete mode 100644 pmoupnp/devices/services/statevariables/valuerange.go delete mode 100644 pmoupnp/events.go delete mode 100644 pmoupnp/interface.go delete mode 100644 pmoupnp/objectstore/object.go delete mode 100644 pmoupnp/objectstore/objectset.go delete mode 100644 pmoupnp/server.go delete mode 100644 pmoupnp/service.go delete mode 100644 pmoupnp/serviceinstance.go delete mode 100644 pmoupnp/serviceinstanceset.go delete mode 100644 pmoupnp/serviceset.go delete mode 100644 pmoupnp/srv_reg_devices.go delete mode 100644 soap/buildsoap.go delete mode 100644 soap/markdown.go delete mode 100644 soap/parseSoap.go delete mode 100644 ssdp/server.go delete mode 100644 xx diff --git a/.gitignore b/.gitignore index be2495b9..7551fafb 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,7 @@ xxx C/src/soxr-0.1.3/Release/tests **/Release/ **/Debug/ +OLD-GO-CODE/ +xxx +xx +all.txt diff --git a/C/include/soxr-lsr.h b/C/include/soxr-lsr.h deleted file mode 100644 index b1cc2470..00000000 --- a/C/include/soxr-lsr.h +++ /dev/null @@ -1,78 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-18 robs@users.sourceforge.net - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* Wrapper compatible with `libsamplerate' (constant-rate). - * (Libsoxr's native API can be found in soxr.h). */ - -#if !defined SAMPLERATE_H -#define SAMPLERATE_H -#if defined __cplusplus - extern "C" { -#endif - -#if defined SOXR_DLL - #if defined soxr_lsr_EXPORTS - #define SOXR __declspec(dllexport) - #else - #define SOXR __declspec(dllimport) - #endif -#elif defined SOXR_VISIBILITY && defined __GNUC__ && (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 1) - #define SOXR __attribute__ ((visibility("default"))) -#else - #define SOXR -#endif - -typedef float SRC_SAMPLE; -enum SRC_SRCTYPE_e {SRC_SINC_BEST_QUALITY, SRC_SINC_MEDIUM_QUALITY, - SRC_SINC_FASTEST, SRC_ZERO_ORDER_HOLD, SRC_LINEAR}; -typedef int SRC_SRCTYPE; -typedef int SRC_ERROR; -typedef long (* src_callback_t)(void *, SRC_SAMPLE * *); -typedef struct soxr SRC_STATE; -typedef struct SRC_DATA { - SRC_SAMPLE * data_in, * data_out; - long input_frames, output_frames; - long input_frames_used, output_frames_gen; - int end_of_input; - double src_ratio; -} SRC_DATA; -SOXR SRC_STATE * src_new(SRC_SRCTYPE, int num_channels, SRC_ERROR *); -SOXR SRC_ERROR src_process (SRC_STATE *, SRC_DATA *); -SOXR SRC_ERROR src_set_ratio(SRC_STATE *, double); -SOXR SRC_ERROR src_reset (SRC_STATE *); -SOXR SRC_ERROR src_error (SRC_STATE *); -SOXR SRC_STATE * src_delete (SRC_STATE *); -SOXR SRC_STATE * src_callback_new( - src_callback_t, SRC_SRCTYPE, int, SRC_ERROR *, void *); -SOXR long src_callback_read( - SRC_STATE *, double src_ratio, long, SRC_SAMPLE *); -SOXR SRC_ERROR src_simple(SRC_DATA *, SRC_SRCTYPE, int); -SOXR char const * src_get_name(SRC_SRCTYPE); -SOXR char const * src_get_description(SRC_SRCTYPE); -SOXR char const * src_get_version(void); -SOXR char const * src_strerror(SRC_ERROR); -SOXR int src_is_valid_ratio(double); -SOXR void src_short_to_float_array(short const *, float *, int); -SOXR void src_float_to_short_array(float const *, short *, int); -SOXR void src_int_to_float_array(int const *, float *, int); -SOXR void src_float_to_int_array(float const *, int *, int); - -#undef SOXR -#if defined __cplusplus - } -#endif -#endif diff --git a/C/include/soxr.h b/C/include/soxr.h deleted file mode 100644 index 09ec7c46..00000000 --- a/C/include/soxr.h +++ /dev/null @@ -1,344 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-18 robs@users.sourceforge.net - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - - - -/* -------------------------------- Gubbins --------------------------------- */ - -#if !defined soxr_included -#define soxr_included - - -#if defined __cplusplus - #include - extern "C" { -#else - #include -#endif - -#if defined SOXR_DLL - #if defined soxr_EXPORTS - #define SOXR __declspec(dllexport) - #else - #define SOXR __declspec(dllimport) - #endif -#elif defined SOXR_VISIBILITY && defined __GNUC__ && (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 1) - #define SOXR __attribute__ ((visibility("default"))) -#else - #define SOXR -#endif - -typedef struct soxr_io_spec soxr_io_spec_t; -typedef struct soxr_quality_spec soxr_quality_spec_t; -typedef struct soxr_runtime_spec soxr_runtime_spec_t; - - - -/* ---------------------------- API conventions -------------------------------- - -Buffer lengths (and occupancies) are expressed as the number of contained -samples per channel. - -Parameter names for buffer lengths have the suffix `len'. - -A single-character `i' or 'o' is often used in names to give context as -input or output (e.g. ilen, olen). */ - - - -/* --------------------------- Version management --------------------------- */ - -/* E.g. #if SOXR_THIS_VERSION >= SOXR_VERSION(0,1,1) ... */ - -#define SOXR_VERSION(x,y,z) (((x)<<16)|((y)<<8)|(z)) -#define SOXR_THIS_VERSION SOXR_VERSION(0,1,3) -#define SOXR_THIS_VERSION_STR "0.1.3" - - - -/* --------------------------- Type declarations ---------------------------- */ - -typedef struct soxr * soxr_t; /* A resampler for 1 or more channels. */ -typedef char const * soxr_error_t; /* 0:no-error; non-0:error. */ - -typedef void * soxr_buf_t; /* 1 buffer of channel-interleaved samples. */ -typedef void const * soxr_cbuf_t; /* Ditto; read-only. */ - -typedef soxr_buf_t const * soxr_bufs_t;/* Or, a separate buffer for each ch. */ -typedef soxr_cbuf_t const * soxr_cbufs_t; /* Ditto; read-only. */ - -typedef void const * soxr_in_t; /* Either a soxr_cbuf_t or soxr_cbufs_t, - depending on itype in soxr_io_spec_t. */ -typedef void * soxr_out_t; /* Either a soxr_buf_t or soxr_bufs_t, - depending on otype in soxr_io_spec_t. */ - - - -/* --------------------------- API main functions --------------------------- */ - -SOXR char const * soxr_version(void); /* Query library version: "libsoxr-x.y.z" */ - -#define soxr_strerror(e) /* Soxr counterpart to strerror. */ \ - ((e)?(e):"no error") - - -/* Create a stream resampler: */ - -SOXR soxr_t soxr_create( - double input_rate, /* Input sample-rate. */ - double output_rate, /* Output sample-rate. */ - unsigned num_channels, /* Number of channels to be used. */ - /* All following arguments are optional (may be set to NULL). */ - soxr_error_t *, /* To report any error during creation. */ - soxr_io_spec_t const *, /* To specify non-default I/O formats. */ - soxr_quality_spec_t const *, /* To specify non-default resampling quality.*/ - soxr_runtime_spec_t const *);/* To specify non-default runtime resources. - - Default io_spec is per soxr_io_spec(SOXR_FLOAT32_I, SOXR_FLOAT32_I) - Default quality_spec is per soxr_quality_spec(SOXR_HQ, 0) - Default runtime_spec is per soxr_runtime_spec(1) */ - - - -/* If not using an app-supplied input function, after creating a stream - * resampler, repeatedly call: */ - -SOXR soxr_error_t soxr_process( - soxr_t resampler, /* As returned by soxr_create. */ - /* Input (to be resampled): */ - soxr_in_t in, /* Input buffer(s); may be NULL (see below). */ - size_t ilen, /* Input buf. length (samples per channel). */ - size_t * idone, /* To return actual # samples used (<= ilen). */ - /* Output (resampled): */ - soxr_out_t out, /* Output buffer(s).*/ - size_t olen, /* Output buf. length (samples per channel). */ - size_t * odone); /* To return actual # samples out (<= olen). - - Note that no special meaning is associated with ilen or olen equal to - zero. End-of-input (i.e. no data is available nor shall be available) - may be indicated by seting `in' to NULL. */ - - - -/* If using an app-supplied input function, it must look and behave like this:*/ - -typedef size_t /* data_len */ - (* soxr_input_fn_t)( /* Supply data to be resampled. */ - void * input_fn_state, /* As given to soxr_set_input_fn (below). */ - soxr_in_t * data, /* Returned data; see below. N.B. ptr to ptr(s)*/ - size_t requested_len); /* Samples per channel, >= returned data_len. - - data_len *data Indicates Meaning - ------- ------- ------------ ------------------------- - !=0 !=0 Success *data contains data to be - input to the resampler. - 0 !=0 (or End-of-input No data is available nor - not set) shall be available. - 0 0 Failure An error occurred whilst trying to - source data to be input to the resampler. */ - -/* and be registered with a previously created stream resampler using: */ - -SOXR soxr_error_t soxr_set_input_fn(/* Set (or reset) an input function.*/ - soxr_t resampler, /* As returned by soxr_create. */ - soxr_input_fn_t, /* Function to supply data to be resampled.*/ - void * input_fn_state, /* If needed by the input function. */ - size_t max_ilen); /* Maximum value for input fn. requested_len.*/ - -/* then repeatedly call: */ - -SOXR size_t /*odone*/ soxr_output(/* Resample and output a block of data.*/ - soxr_t resampler, /* As returned by soxr_create. */ - soxr_out_t data, /* App-supplied buffer(s) for resampled data.*/ - size_t olen); /* Amount of data to output; >= odone. */ - - - -/* Common stream resampler operations: */ - -SOXR soxr_error_t soxr_error(soxr_t); /* Query error status. */ -SOXR size_t * soxr_num_clips(soxr_t); /* Query int. clip counter (for R/W). */ -SOXR double soxr_delay(soxr_t); /* Query current delay in output samples.*/ -SOXR char const * soxr_engine(soxr_t); /* Query resampling engine name. */ - -SOXR soxr_error_t soxr_clear(soxr_t); /* Ready for fresh signal, same config. */ -SOXR void soxr_delete(soxr_t); /* Free resources. */ - - - -/* `Short-cut', single call to resample a (probably short) signal held entirely - * in memory. See soxr_create and soxr_process above for parameter details. - * Note that unlike soxr_create however, the default quality spec. for - * soxr_oneshot is per soxr_quality_spec(SOXR_LQ, 0). */ - -SOXR soxr_error_t soxr_oneshot( - double input_rate, - double output_rate, - unsigned num_channels, - soxr_in_t in , size_t ilen, size_t * idone, - soxr_out_t out, size_t olen, size_t * odone, - soxr_io_spec_t const *, - soxr_quality_spec_t const *, - soxr_runtime_spec_t const *); - - - -/* For variable-rate resampling. See example # 5 for how to create a - * variable-rate resampler and how to use this function. */ - -SOXR soxr_error_t soxr_set_io_ratio(soxr_t, double io_ratio, size_t slew_len); - - - -/* -------------------------- API type definitions -------------------------- */ - -typedef enum { /* Datatypes supported for I/O to/from the resampler: */ - /* Internal; do not use: */ - SOXR_FLOAT32, SOXR_FLOAT64, SOXR_INT32, SOXR_INT16, SOXR_SPLIT = 4, - - /* Use for interleaved channels: */ - SOXR_FLOAT32_I = SOXR_FLOAT32, SOXR_FLOAT64_I, SOXR_INT32_I, SOXR_INT16_I, - - /* Use for split channels: */ - SOXR_FLOAT32_S = SOXR_SPLIT , SOXR_FLOAT64_S, SOXR_INT32_S, SOXR_INT16_S - -} soxr_datatype_t; - -#define soxr_datatype_size(x) /* Returns `sizeof' a soxr_datatype_t sample. */\ - ((unsigned char *)"\4\10\4\2")[(x)&3] - - - -struct soxr_io_spec { /* Typically */ - soxr_datatype_t itype; /* Input datatype. SOXR_FLOAT32_I */ - soxr_datatype_t otype; /* Output datatype. SOXR_FLOAT32_I */ - double scale; /* Linear gain to apply during resampling. 1 */ - void * e; /* Reserved for internal use 0 */ - unsigned long flags; /* Per the following #defines. 0 */ -}; - -#define SOXR_TPDF 0 /* Applicable only if otype is INT16. */ -#define SOXR_NO_DITHER 8u /* Disable the above. */ - - - -struct soxr_quality_spec { /* Typically */ - double precision; /* Conversion precision (in bits). 20 */ - double phase_response; /* 0=minimum, ... 50=linear, ... 100=maximum 50 */ - double passband_end; /* 0dB pt. bandwidth to preserve; nyquist=1 0.913*/ - double stopband_begin; /* Aliasing/imaging control; > passband_end 1 */ - void * e; /* Reserved for internal use. 0 */ - unsigned long flags; /* Per the following #defines. 0 */ -}; - -#define SOXR_ROLLOFF_SMALL 0u /* <= 0.01 dB */ -#define SOXR_ROLLOFF_MEDIUM 1u /* <= 0.35 dB */ -#define SOXR_ROLLOFF_NONE 2u /* For Chebyshev bandwidth. */ - -#define SOXR_HI_PREC_CLOCK 8u /* Increase `irrational' ratio accuracy. */ -#define SOXR_DOUBLE_PRECISION 16u /* Use D.P. calcs even if precision <= 20. */ -#define SOXR_VR 32u /* Variable-rate resampling. */ - - - -struct soxr_runtime_spec { /* Typically */ - unsigned log2_min_dft_size; /* For DFT efficiency. [8,15] 10 */ - unsigned log2_large_dft_size; /* For DFT efficiency. [8,20] 17 */ - unsigned coef_size_kbytes; /* For SOXR_COEF_INTERP_AUTO (below). 400 */ - unsigned num_threads; /* 0: per OMP_NUM_THREADS; 1: 1 thread. 1 */ - void * e; /* Reserved for internal use. 0 */ - unsigned long flags; /* Per the following #defines. 0 */ -}; - /* For `irrational' ratios only: */ -#define SOXR_COEF_INTERP_AUTO 0u /* Auto select coef. interpolation. */ -#define SOXR_COEF_INTERP_LOW 2u /* Man. select: less CPU, more memory. */ -#define SOXR_COEF_INTERP_HIGH 3u /* Man. select: more CPU, less memory. */ - - - -/* -------------------------- API type constructors ------------------------- */ - -/* These functions allow setting of the most commonly-used structure - * parameters, with other parameters being given default values. The default - * values may then be overridden, directly in the structure, if needed. */ - -SOXR soxr_quality_spec_t soxr_quality_spec( - unsigned long recipe, /* Per the #defines immediately below. */ - unsigned long flags); /* As soxr_quality_spec_t.flags. */ - - /* The 5 standard qualities found in SoX: */ -#define SOXR_QQ 0 /* 'Quick' cubic interpolation. */ -#define SOXR_LQ 1 /* 'Low' 16-bit with larger rolloff. */ -#define SOXR_MQ 2 /* 'Medium' 16-bit with medium rolloff. */ -#define SOXR_HQ SOXR_20_BITQ /* 'High quality'. */ -#define SOXR_VHQ SOXR_28_BITQ /* 'Very high quality'. */ - -#define SOXR_16_BITQ 3 -#define SOXR_20_BITQ 4 -#define SOXR_24_BITQ 5 -#define SOXR_28_BITQ 6 -#define SOXR_32_BITQ 7 - /* Reserved for internal use (to be removed): */ -#define SOXR_LSR0Q 8 /* 'Best sinc'. */ -#define SOXR_LSR1Q 9 /* 'Medium sinc'. */ -#define SOXR_LSR2Q 10 /* 'Fast sinc'. */ - -#define SOXR_LINEAR_PHASE 0x00 -#define SOXR_INTERMEDIATE_PHASE 0x10 -#define SOXR_MINIMUM_PHASE 0x30 - -#define SOXR_STEEP_FILTER 0x40 - - - -SOXR soxr_runtime_spec_t soxr_runtime_spec( - unsigned num_threads); - - - -SOXR soxr_io_spec_t soxr_io_spec( - soxr_datatype_t itype, - soxr_datatype_t otype); - - - -/* --------------------------- Advanced use only ---------------------------- */ - -/* For new designs, the following functions/usage will probably not be needed. - * They might be useful when adding soxr into an existing design where values - * for the resampling-rate and/or number-of-channels parameters to soxr_create - * are not available when that function will be called. In such cases, the - * relevant soxr_create parameter(s) can be given as 0, then one or both of the - * following (as appropriate) later invoked (but prior to calling soxr_process - * or soxr_output): - * - * soxr_set_error(soxr, soxr_set_io_ratio(soxr, io_ratio, 0)); - * soxr_set_error(soxr, soxr_set_num_channels(soxr, num_channels)); - */ - -SOXR soxr_error_t soxr_set_error(soxr_t, soxr_error_t); -SOXR soxr_error_t soxr_set_num_channels(soxr_t, unsigned); - - - -#undef SOXR - -#if defined __cplusplus -} -#endif - -#endif diff --git a/C/lib/libsoxr-lsr.a b/C/lib/libsoxr-lsr.a deleted file mode 100644 index 481b198d5b61d51abb9bdf245d8aa19b00c2d68c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5992 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 ba3Cn|RTG0U7>*m&c&yw(cdXfB4HNzcg$G^j diff --git a/C/lib/pkgconfig/soxr-lsr.pc b/C/lib/pkgconfig/soxr-lsr.pc deleted file mode 100644 index bcd8a44b..00000000 --- a/C/lib/pkgconfig/soxr-lsr.pc +++ /dev/null @@ -1,5 +0,0 @@ -Name: soxr-lsr -Description: High quality, one-dimensional sample-rate conversion library (with libsamplerate-like bindings) -Version: 0.1.3 -Libs: -L/Users/coissac/Sync/maison/Petite_maisons/src/pmomusic/C/lib -lsoxr-lsr -Cflags: -I/Users/coissac/Sync/maison/Petite_maisons/src/pmomusic/C/include diff --git a/C/lib/pkgconfig/soxr.pc b/C/lib/pkgconfig/soxr.pc deleted file mode 100644 index e54e1436..00000000 --- a/C/lib/pkgconfig/soxr.pc +++ /dev/null @@ -1,5 +0,0 @@ -Name: soxr -Description: High quality, one-dimensional sample-rate conversion library -Version: 0.1.3 -Libs: -L/Users/coissac/Sync/maison/Petite_maisons/src/pmomusic/C/lib -lsoxr -Cflags: -I/Users/coissac/Sync/maison/Petite_maisons/src/pmomusic/C/include diff --git a/C/share/doc/libsoxr/LICENCE b/C/share/doc/libsoxr/LICENCE deleted file mode 100644 index 43e5a716..00000000 --- a/C/share/doc/libsoxr/LICENCE +++ /dev/null @@ -1,23 +0,0 @@ -SoX Resampler Library Copyright (c) 2007-18 robs@users.sourceforge.net - -This library is free software; you can redistribute it and/or modify it -under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation; either version 2.1 of the License, or (at -your option) any later version. - -This library is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser -General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with this library; if not, see . - - -Notes - -1. Re software in the `examples' directory: works that are not resampling -examples but are based on the given examples -- for example, applications using -the library -- shall not be considered to be derivative works of the examples. - -2. If building with pffft.c, see the licence embedded in that file. diff --git a/C/share/doc/libsoxr/NEWS b/C/share/doc/libsoxr/NEWS deleted file mode 100644 index 9e7c298f..00000000 --- a/C/share/doc/libsoxr/NEWS +++ /dev/null @@ -1,46 +0,0 @@ -Version 0.1.3 (2018-02-24) - * SIMD enhancements: SSE, AVX, Neon. - * Improve support for clang, ARM, and cross-compilation. - * Provide env. var. override of runtime parameters. - * Build fix re cmake variables AVCODEC_INCLUDE_DIRS & AVUTIL_INCLUDE_DIRS. - * Build options WITH_SINGLE_PRECISION, WITH_DOUBLE_PRECISION & WITH_SIMD have - been removed; replacement options are detailed in INSTALL, `Resampling - engines'. - -Version 0.1.2 (2015-09-05) - * Fix conversion failure when I/O types differ but I/O rates don't. - * Fix #defines for interpolation order selection. - * Fix ineffectual SOXR_MINIMUM_PHASE and SOXR_INTERMEDIATE_PHASE in - soxr_quality_spec recipe. - * Fix soxr_delay() returning a negative number after end-of-input has been - indicated. - * Fix crash when using soxr_process() after calling soxr_clear(). - * Be more POSIX compliant w.r.t. errno in the examples; fixes erroneous - reporting of errors on FreeBSD. - * Quality improvement for variable-rate. - * Various fixes/improvements to build/tests/documentation. - -Version 0.1.1 (2013-03-03) - * Minor fixes/improvements to build/tests. - * Fix crash (e.g. with k3b) when null error pointer passed to src_create (lsr - bindings only). - * Fix broken resampling in many cases with SIMD and anti_aliasing_pc < 100. - * For clarity, renamed and slightly changed usage of three parameters in - soxr_quality_spec_t (ABI compatible, API incompatible). An application not - setting these parameters directly need make no change; otherwise, changes - should be made per the following example (as shown, compatibility with both - old/new APIs is maintained). See also the comments on these parameters in - soxr.h. N.B. ABI compatibility with the 0.1.0 API may be removed in a - future release. - #if !defined SOXR_VERSION /* Deprecated, 0.1.0 API */ - q_spec.phase = minimum_phase? 0 : 50; - q_spec.bw_pc = cutoff * 100; - q_spec.anti_aliasing_pc = anti_aliasing * 100; - #else /* 0.1.1 API */ Explanation: - q_spec.phase_response = minimum_phase? 0 : 50; Renamed. - q_spec.passband_end = cutoff; Renamed, no longer %. - q_spec.stopband_begin = 2 - anti_aliasing; Renamed, no longer %, no - #endif longer mirrored in Fs. - -Version 0.1.0 (2013-01-19) - * First public release. diff --git a/C/share/doc/libsoxr/README b/C/share/doc/libsoxr/README deleted file mode 100644 index 7f9a7afb..00000000 --- a/C/share/doc/libsoxr/README +++ /dev/null @@ -1,53 +0,0 @@ -SoX Resampler Library Copyright (c) 2007-18 robs@users.sourceforge.net - -The SoX Resampler library `libsoxr' performs one-dimensional sample-rate -conversion -- it may be used, for example, to resample PCM-encoded audio. -For higher-dimensional resampling, such as for visual-image processing, you -should look elsewhere. - -It aims to give fast¹ and very high quality² results for any constant -(rational or irrational) resampling ratio. Phase-response, preserved -bandwidth, aliasing, and rejection level parameters are all configurable; -alternatively, simple `preset' configurations may be selected. A -variable-rate resampling mode of operation is also included. - -The resampler is currently available either as part of `libsox' (the audio -file-format and effect library), or stand-alone as `libsoxr' (this package). -The interfaces to libsox and libsoxr are slightly different, with that of -libsoxr designed specifically for resampling. An application requiring -support for other effects, or for reading-from or writing-to audio files or -devices, should use libsox (or other libraries such as libsndfile or -libavformat). - -Libsoxr provides a simple API that allows interfacing using the most -commonly-used sample formats and buffering schemes: sample-formats may be -either floating-point or integer, and multiple channels either interleaved -or split in separate buffers. The API is documented in the header file -`soxr.h', together with sample code found in the 'examples' directory. - -For compatibility with the popular `libsamplerate' library, the header file -`soxr-lsr.h' is provided and may be used as an alternative API.³ Note -however, that libsoxr does not provide a full emulation of libsamplerate -and that using this approach, only a sub-set of libsoxr's features are -available. - -The design was inspired by Laurent De Soras' paper `The Quest For The -Perfect Resampler', http://ldesoras.free.fr/doc/articles/resampler-en.pdf; -in essence, it combines Julius O. Smith's `Bandlimited Interpolation' -technique (https://ccrma.stanford.edu/~jos/resample/resample.pdf) with FFT- -based over-sampling. - -Note that for real-time resampling, libsoxr may have a higher latency -than non-FFT based resamplers. For example, when using the `High Quality' -configuration to resample between 44100Hz and 48000Hz, the latency is -around 1000 output samples, i.e. roughly 20ms (though passband and FFT- -size configuration parameters may be used to reduce this figure). - -For build and installation instructions, see the file `INSTALL'; for -copyright and licensing information, see the file `LICENCE'. - -For support and new versions, see https://soxr.sourceforge.net -________ -¹ For example, multi-channel resampling can utilise multiple CPU-cores. -² Bit-perfect within practical occupied-bandwidth limits. -³ For details of that API, see http://www.mega-nerd.com/SRC/api.html. diff --git a/C/share/doc/libsoxr/examples/1-single-block.c b/C/share/doc/libsoxr/examples/1-single-block.c deleted file mode 100644 index 3b919b45..00000000 --- a/C/share/doc/libsoxr/examples/1-single-block.c +++ /dev/null @@ -1,50 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -/* Example 1: `One-shot' resample a single block of data in memory. - * - * N.B. See example 2 for how to resample a stream (of blocks). - * - * Optional arguments are: INPUT-RATE OUTPUT-RATE - * - * With the default arguments, the output should produce lines similar to the - * following: - * - * 0.00 0.71 1.00 0.71 -0.00 -0.71 -1.00 -0.71 - * - * Gibbs effect may be seen at the ends of the resampled signal; this is because - * unlike a `real-world' signal, the synthetic input signal is not band-limited. - */ - -#include -#include "examples-common.h" - -const float in[] = { /* Input: 12 cycles of a sine wave with freq. = irate/4 */ - 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, - 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1}; - -int main(int argc, char const * arg[]) -{ - double irate = argc > 1? atof(arg[1]) : 1; /* Default to interpolation */ - double orate = argc > 2? atof(arg[2]) : 2; /* by a factor of 2. */ - - size_t olen = (size_t)(AL(in) * orate / irate + .5); /* Assay output len. */ - float * out = malloc(sizeof(*out) * olen); /* Allocate output buffer. */ - size_t odone; - - soxr_error_t error = soxr_oneshot(irate, orate, 1, /* Rates and # of chans. */ - in, AL(in), NULL, /* Input. */ - out, olen, &odone, /* Output. */ - NULL, NULL, NULL); /* Default configuration.*/ - - unsigned i = 0; /* Print out the resampled data, */ - while (i++ < odone) - printf("%5.2f%c", out[i-1], " \n"[!(i&7) || i == odone]); - printf("%-26s %s\n", arg[0], soxr_strerror(error)); /* and reported result. */ - - if (argc > 3) /* Library version check: */ - printf("runtime=%s API="SOXR_THIS_VERSION_STR"\n", soxr_version()); - - free(out); /* Tidy up. */ - return !!error; -} diff --git a/C/share/doc/libsoxr/examples/1a-lsr.c b/C/share/doc/libsoxr/examples/1a-lsr.c deleted file mode 100644 index 6b50a8f5..00000000 --- a/C/share/doc/libsoxr/examples/1a-lsr.c +++ /dev/null @@ -1,40 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -/* Example 1a: Variant of example 1 using libsamplerate-like bindings. */ - -#include -#include "examples-common.h" - -float in[] = { /* Input: 12 cycles of a sine wave with freq. = irate/4 */ - 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, - 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1}; - -int main(int argc, char const * arg[]) -{ - double irate = argc > 1? atof(arg[1]) : 1; /* Default to interpolation */ - double orate = argc > 2? atof(arg[2]) : 2; /* by a factor of 2. */ - - size_t olen = (size_t)(AL(in) * orate / irate + .5); /* Assay output len. */ - float * out = (float *)malloc(sizeof(*out) * olen); /* Allocate output buf. */ - - int error, i = 0; - SRC_DATA data; - - data.data_in = in; - data.data_out = out; - data.input_frames = AL(in); - data.output_frames = (int)olen; - data.src_ratio = orate / irate; - error = src_simple(&data, SRC_SINC_FASTEST, 1); - - while (i++ < data.output_frames_gen) /* Print out the resampled data, */ - printf("%5.2f%c", out[i-1], " \n"[!(i&7) || i == data.output_frames_gen]); - printf("%-26s %s\n", arg[0], src_strerror(error)); /* and reported result. */ - - if (argc > 3) /* Library version check: */ - printf("runtime=%s\n", src_get_version()); - - free(out); /* Tidy up. */ - return !!error; -} diff --git a/C/share/doc/libsoxr/examples/2-stream.C b/C/share/doc/libsoxr/examples/2-stream.C deleted file mode 100644 index 29c1bf62..00000000 --- a/C/share/doc/libsoxr/examples/2-stream.C +++ /dev/null @@ -1,78 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -/* Example 2: resample a raw, single-channel, floating-point data stream from - * stdin to stdout. - * - * The application uses the single function `soxr_process' for both input and - * output to/from the resampler; compared to the `input function' approach - * (illustrated in example 3) this requires that the application implements - * more logic, but one less function. - * - * Arguments are: INPUT-RATE OUTPUT-RATE - */ - -#include -#include "examples-common.h" - -int main(int argc, char const * arg[]) -{ - double const irate = argc > 1? atof(arg[1]) : 96000.; - double const orate = argc > 2? atof(arg[2]) : 44100.; - - /* Allocate resampling input and output buffers in proportion to the input - * and output rates: */ - #define buf_total_len 15000 /* In samples. */ - size_t const olen = (size_t)(orate * buf_total_len / (irate + orate) + .5); - size_t const ilen = buf_total_len - olen; - size_t const osize = sizeof(float), isize = osize; - void * obuf = malloc(osize * olen); - void * ibuf = malloc(isize * ilen); - - size_t odone, written, need_input = 1; - soxr_error_t error; - - /* Create a stream resampler: */ - soxr_t soxr = soxr_create( - irate, orate, 1, /* Input rate, output rate, # of channels. */ - &error, /* To report any error during creation. */ - NULL, NULL, NULL); /* Use configuration defaults.*/ - - if (!error) { /* If all is well, run the resampler: */ - USE_STD_STDIO; - /* Resample in blocks: */ - do { - size_t ilen1 = 0; - - if (need_input) { - - /* Read one block into the buffer, ready to be resampled: */ - ilen1 = fread(ibuf, isize, ilen, stdin); - - if (!ilen1) { /* If the is no (more) input data available, */ - free(ibuf); /* set ibuf to NULL, to indicate end-of-input */ - ibuf = NULL; /* to the resampler. */ - } - } - - /* Copy data from the input buffer into the resampler, and resample - * to produce as much output as is possible to the given output buffer: */ - error = soxr_process(soxr, ibuf, ilen1, NULL, obuf, olen, &odone); - - written = fwrite(obuf, osize, odone, stdout); /* Consume output.*/ - - /* If the actual amount of data output is less than that requested, and - * we have not already reached the end of the input data, then supply some - * more input next time round the loop: */ - need_input = odone < olen && ibuf; - - } while (!error && (need_input || written)); - } - /* Tidy up: */ - soxr_delete(soxr); - free(obuf), free(ibuf); - /* Diagnostics: */ - fprintf(stderr, "%-26s %s; I/O: %s\n", arg[0], soxr_strerror(error), - ferror(stdin) || ferror(stdout)? strerror(errno) : "no error"); - return !!error; -} diff --git a/C/share/doc/libsoxr/examples/3-options-input-fn.c b/C/share/doc/libsoxr/examples/3-options-input-fn.c deleted file mode 100644 index afd43b9f..00000000 --- a/C/share/doc/libsoxr/examples/3-options-input-fn.c +++ /dev/null @@ -1,114 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -/* Example 3: extends example 2 with multiple channels, multiple datatypes, - * and other options. - * - * The application provides an input function, called on demand by libsoxr, in - * response to calls to soxr_output(); compared to the `process' approach - * (illustrated in example 2) this requires that the application implements - * less logic, but one more function. - * - * The 11 arguments (which are optional, from last to first) are: - * INPUT-RATE As example 2 - * OUTPUT-RATE Ditto - * NUM-CHANNELS Number of interleaved channels - * IN-DATATYPE# 0:float32 1:float64 2:int32 3:int16 - * OUT-DATATYPE# Ditto; or 11 for un-dithered int16 - * Q-RECIPE Quality recipe (in hex) See soxr.h - * Q-FLAGS Quality flags (in hex) See soxr.h - * PASSBAND-END % - * STOPBAND-BEGIN % - * PHASE-RESPONSE [0,100] - * USE-THREADS 1 to use multi-threading (where available) - */ - -#include -#include "examples-common.h" - -typedef struct {void * ibuf; size_t isize;} input_context_t; - -static size_t input_fn(input_context_t * p, soxr_cbuf_t * buf, size_t len) -{ - /* Read one block into the buffer, ready to be input to the resampler: */ - len = fread(p->ibuf, p->isize, len, stdin); /* Actual len read may be less. */ - - /* Inform the resampler of the data's whereabouts (which could be anywhere, in - * a freshly malloc'd buffer, for example): */ - *buf = (!len && ferror(stdin))? NULL : p->ibuf; /* NULL if error occurred. */ - - return len; /* # of samples per channel to input. */ -} - -int main(int n, char const * arg[]) -{ - char const * const arg0 = n? --n, *arg++ : "", * engine = ""; - double const irate = n? --n, atof(*arg++) : 96000.; - double const orate = n? --n, atof(*arg++) : 44100.; - unsigned const chans = n? --n, (unsigned)atoi(*arg++) : 1; - soxr_datatype_t const itype = n? --n, (soxr_datatype_t)atoi(*arg++) : 0; - unsigned const ospec = n? --n, (soxr_datatype_t)atoi(*arg++) : 0; - unsigned long const q_recipe= n? --n, strtoul(*arg++, 0, 16) : SOXR_HQ; - unsigned long const q_flags = n? --n, strtoul(*arg++, 0, 16) : 0; - double const passband_end = n? --n, atof(*arg++) : 0; - double const stopband_begin = n? --n, atof(*arg++) : 0; - double const phase_response = n? --n, atof(*arg++) : -1; - int const use_threads = n? --n, atoi(*arg++) : 1; - soxr_datatype_t const otype = ospec & 3; - - soxr_quality_spec_t q_spec = soxr_quality_spec(q_recipe, q_flags); - soxr_io_spec_t io_spec = soxr_io_spec(itype, otype); - soxr_runtime_spec_t const runtime_spec = soxr_runtime_spec(!use_threads); - - /* Allocate resampling input and output buffers in proportion to the input - * and output rates: */ - #define buf_total_len 15000 /* In samples per channel. */ - size_t const osize = soxr_datatype_size(otype) * chans; - size_t const isize = soxr_datatype_size(itype) * chans; - size_t const olen0= (size_t)(orate * buf_total_len / (irate + orate) + .5); - size_t const olen = min(max(olen0, 1), buf_total_len - 1); - size_t const ilen = buf_total_len - olen; - void * const obuf = malloc(osize * olen); - void * const ibuf = malloc(isize * ilen); - - input_context_t icontext; - size_t odone, clips = 0; - soxr_error_t error; - soxr_t soxr; - - /* Overrides (if given): */ - if (passband_end > 0) q_spec.passband_end = passband_end / 100; - if (stopband_begin > 0) q_spec.stopband_begin = stopband_begin / 100; - if (phase_response >=0) q_spec.phase_response = phase_response; - io_spec.flags = ospec & ~7u; - - /* Create a stream resampler: */ - soxr = soxr_create( - irate, orate, chans, /* Input rate, output rate, # of channels. */ - &error, /* To report any error during creation. */ - &io_spec, &q_spec, &runtime_spec); - - if (!error) { /* Register input_fn with the resampler: */ - icontext.ibuf = ibuf, icontext.isize = isize; - error = soxr_set_input_fn(soxr, (soxr_input_fn_t)input_fn, &icontext, ilen); - } - - if (!error) { /* If all is well, run the resampler: */ - engine = soxr_engine(soxr); - USE_STD_STDIO; - /* Resample in blocks: */ - do odone = soxr_output(soxr, obuf, olen); - while (fwrite(obuf, osize, odone, stdout)); /* Consume output. */ - - error = soxr_error(soxr); /* Check if any soxr error occurred. */ - clips = *soxr_num_clips(soxr); /* Can occur only with integer output. */ - } - /* Tidy up: */ - soxr_delete(soxr); - free(obuf), free(ibuf); - /* Diagnostics: */ - fprintf(stderr, "%-26s %s; %lu clips; I/O: %s (%s)\n", - arg0, soxr_strerror(error), (long unsigned)clips, - ferror(stdin) || ferror(stdout)? strerror(errno) : "no error", engine); - return !!error; -} diff --git a/C/share/doc/libsoxr/examples/4-split-channels.c b/C/share/doc/libsoxr/examples/4-split-channels.c deleted file mode 100644 index a9022ce0..00000000 --- a/C/share/doc/libsoxr/examples/4-split-channels.c +++ /dev/null @@ -1,161 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-18 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -/* Example 4: variant of examples 2 & 3, demonstrating I/O with split channels. - * - * Note that, for convenience of the demonstration, split-channel data is - * made available by deinterleaving data sourced from and sent to - * interleaved file-streams; this adds a lot of code to the example that, - * for purposes of understanding how to use split-channels, may safely be - * ignored. In a real application, the channel-data might never be - * interleaved; for example, the split-channel data output from the - * resampler might be sent directly to digital-to-analogue converters. - * - * Note also (not shown in the examples) that split/interleaved channels may - * be used for input and output independently. - * - * Arguments are as example 3. - */ - -#include -#include "examples-common.h" - - - -#define DEINTERLEAVE(T) do { \ - unsigned i; \ - size_t j; \ - T * const * dest = (T * const *)dest0; \ - T const * src = src0; \ - if (ch == 1) memcpy(dest[0], src, n * sizeof(dest[0][0])); \ - else for (j = 0; j < n; ++j) for (i = 0; i < ch; ++i) dest[i][j] = *src++; \ - return; \ -} while (0) - -static void deinterleave(soxr_datatype_t data_type, - void * const * dest0, - void const * src0, - size_t n, unsigned ch) -{ - switch (data_type & 3) { - case SOXR_FLOAT32: DEINTERLEAVE(float); - case SOXR_FLOAT64: DEINTERLEAVE(double); - case SOXR_INT32 : DEINTERLEAVE(int32_t); - case SOXR_INT16 : DEINTERLEAVE(int16_t); - default: break; - } -} - -#define INTERLEAVE(T) do { \ - unsigned i; \ - size_t j; \ - T * dest = dest0; \ - T const * const * src = (T const * const *)src0; \ - if (ch == 1) memcpy(dest, src[0], n * sizeof(dest[0])); \ - else for (j = 0; j < n; ++j) for (i = 0; i < ch; ++i) *dest++ = src[i][j]; \ - return; \ -} while (0) - -static void interleave(soxr_datatype_t data_type, void * dest0, - void * const * src0, size_t n, unsigned ch) -{ - switch (data_type & 3) { - case SOXR_FLOAT32: INTERLEAVE(float); - case SOXR_FLOAT64: INTERLEAVE(double); - case SOXR_INT32 : INTERLEAVE(int32_t); - case SOXR_INT16 : INTERLEAVE(int16_t); - default: break; - } -} - -int main(int n, char const * arg[]) -{ - char const * const arg0 = n? --n, *arg++ : ""; - double const irate = n? --n, atof(*arg++) : 96000.; - double const orate = n? --n, atof(*arg++) : 44100.; - unsigned const chans = n? --n, (unsigned)atoi(*arg++) : 1; - soxr_datatype_t const itype = n? --n, (soxr_datatype_t)atoi(*arg++) : 0; - unsigned const ospec = n? --n, (soxr_datatype_t)atoi(*arg++) : 0; - unsigned long const q_recipe= n? --n, strtoul(*arg++, 0, 16) : SOXR_HQ; - unsigned long const q_flags = n? --n, strtoul(*arg++, 0, 16) : 0; - double const passband_end = n? --n, atof(*arg++) : 0; - double const stopband_begin = n? --n, atof(*arg++) : 0; - double const phase_response = n? --n, atof(*arg++) : -1; - int const use_threads = n? --n, atoi(*arg++) : 1; - soxr_datatype_t const otype = ospec & 3; - - soxr_quality_spec_t q_spec = soxr_quality_spec(q_recipe, q_flags); - soxr_io_spec_t io_spec=soxr_io_spec(itype|SOXR_SPLIT, otype|SOXR_SPLIT); - soxr_runtime_spec_t const runtime_spec = soxr_runtime_spec(!use_threads); - - /* Allocate resampling input and output buffers in proportion to the input - * and output rates: */ - #define buf_total_len 15000 /* In samples per channel. */ - size_t const osize = soxr_datatype_size(otype) * chans; - size_t const isize = soxr_datatype_size(itype) * chans; - size_t const olen = (size_t)(orate * buf_total_len / (irate + orate) + .5); - size_t const ilen = buf_total_len - olen; - - /* For split channels: */ - void * * const obuf_ptrs = malloc(sizeof(void *) * chans); - void * * ibuf_ptrs = malloc(sizeof(void *) * chans); - char * const obufs = malloc(osize * olen), * optr = obufs; - char * const ibufs = malloc(isize * ilen), * iptr = ibufs; - - /* For interleaved channels: */ - char * const obuf = malloc(osize * olen); - char * const ibuf = malloc(isize * ilen); - - size_t odone, written, need_input = 1, clips = 0; - soxr_error_t error; - soxr_t soxr; - unsigned i; - - /* Overrides (if given): */ - if (passband_end > 0) q_spec.passband_end = passband_end / 100; - if (stopband_begin > 0) q_spec.stopband_begin = stopband_begin / 100; - if (phase_response >=0) q_spec.phase_response = phase_response; - io_spec.flags = ospec & ~7u; - - soxr = soxr_create( - irate, orate, chans, &error, &io_spec, &q_spec, &runtime_spec); - - for (i = 0; i < chans; ++i) { - ibuf_ptrs[i] = iptr; - obuf_ptrs[i] = optr; - iptr += ilen * soxr_datatype_size(itype); - optr += olen * soxr_datatype_size(otype); - } - - if (!error) { - USE_STD_STDIO; - - do { - size_t ilen1 = 0; - - if (need_input) { - if (!(ilen1 = fread(ibuf, isize, ilen, stdin))) - free(ibuf_ptrs), ibuf_ptrs = 0; /* If none available, don't retry. */ - else deinterleave(itype, ibuf_ptrs, ibuf, ilen1, chans); - } - - error = soxr_process(soxr, ibuf_ptrs, ilen1, NULL, obuf_ptrs, olen, &odone); - interleave(otype, obuf, obuf_ptrs, odone, chans); /* Consume output... */ - written = fwrite(obuf, osize, odone, stdout); - - need_input = odone < olen && ibuf_ptrs; - - } while (!error && (need_input || written)); - - clips = *soxr_num_clips(soxr); /* Can occur only with integer output. */ - } - /* Tidy up: */ - soxr_delete(soxr); - free(obuf), free(ibuf), free(obufs), free(ibufs); - free(obuf_ptrs), free(ibuf_ptrs); - /* Diagnostics: */ - fprintf(stderr, "%-26s %s; %lu clips; I/O: %s\n", - arg0, soxr_strerror(error), (long unsigned)clips, - ferror(stdin) || ferror(stdout)? strerror(errno) : "no error"); - return !!error; -} diff --git a/C/share/doc/libsoxr/examples/5-variable-rate.c b/C/share/doc/libsoxr/examples/5-variable-rate.c deleted file mode 100644 index 1a1c63f5..00000000 --- a/C/share/doc/libsoxr/examples/5-variable-rate.c +++ /dev/null @@ -1,93 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -/* Example 5: Variable-rate resampling. A test signal (held in a buffer) is - * resampled over a wide range of octaves. Resampled data is sent to stdout as - * raw, float32 samples. Choices of 2 test-signals and of 2 ways of varying - * the sample-rate are combined in a command-line option: - * - * Usage: ./5-variable-rate [0|1|2|3] - */ - -#include -#include "examples-common.h" - -#define OCTAVES 5 /* Resampling range. ± */ -#define OLEN 16 /* Output length in seconds. */ -#define FS 44100 /* Output sampling rate in Hz. */ - -/* For output pos in [0,1], returns an ioratio in the 2^±OCTAVES range: */ -static double ioratio(double pos, int fm) -{ - if (fm) /* fm: non-0 for a fast-changing ioratio, 0 for a slow sweep. */ - pos = .5 - cos(pos * 2 * M_PI) * .4 + sin(pos * OLEN * 20 * M_PI) * .05; - return pow(2, 2 * OCTAVES * pos - OCTAVES); -} - -int main(int argc, char *arg[]) -{ - int opt = argc <= 1? 2 : (atoi(arg[1]) & 3), saw = opt & 1, fm = opt & 2; - float ibuf[10 << OCTAVES], obuf[AL(ibuf)]; - int i, wl = 2 << OCTAVES; - size_t ilen = AL(ibuf), need_input = 1, written; - size_t odone, total_odone, total_olen = OLEN * FS; - size_t olen1 = fm? 10 : AL(obuf); /* Small block-len if fast-changing ratio */ - soxr_error_t error; - - /* When creating a var-rate resampler, q_spec must be set as follows: */ - soxr_quality_spec_t q_spec = soxr_quality_spec(SOXR_HQ, SOXR_VR); - - /* The ratio of the given input rate and output rates must equate to the - * maximum I/O ratio that will be used: */ - soxr_t soxr = soxr_create(1 << OCTAVES, 1, 1, &error, NULL, &q_spec, NULL); - - if (!error) { - USE_STD_STDIO; - - /* Generate input signal, sine or saw, with wave-length = wl: */ - for (i = 0; i < (int)ilen; ++i) - ibuf[i] = (float)(saw? (i%wl)/(wl-1.)-.5 : .9 * sin(2 * M_PI * i / wl)); - - /* Set the initial resampling ratio (N.B. 3rd parameter = 0): */ - soxr_set_io_ratio(soxr, ioratio(0, fm), 0); - - /* Resample in blocks of size olen1: */ - for (total_odone = 0; !error && total_odone < total_olen;) { - - /* The last block might be shorter: */ - size_t block_len = min(olen1, total_olen - total_odone); - - /* Determine the position in [0,1] of the end of the current block: */ - double pos = (double)(total_odone + block_len) / (double)total_olen; - - /* Calculate an ioratio for this position and instruct the resampler to - * move smoothly to the new value, over the course of outputting the next - * 'block_len' samples (or give 0 for an instant change instead): */ - soxr_set_io_ratio(soxr, ioratio(pos, fm), block_len); - - /* Output the block of samples, supplying input samples as needed: */ - do { - size_t len = need_input? ilen : 0; - error = soxr_process(soxr, ibuf, len, NULL, obuf, block_len, &odone); - written = fwrite(obuf, sizeof(float), odone, stdout); - - /* Update counters for the current block and for the total length: */ - block_len -= odone; - total_odone += odone; - - /* If soxr_process did not provide the complete block, we must call it - * again, supplying more input samples: */ - need_input = block_len != 0; - - } while (need_input && !error && written == odone); - - /* Now that the block for the current ioratio is complete, go back - * round the main `for' loop in order to process the next block. */ - } - soxr_delete(soxr); - } - /* Diagnostics: */ - fprintf(stderr, "%-26s %s; I/O: %s\n", arg[0], soxr_strerror(error), - ferror(stdin) || ferror(stdout)? strerror(errno) : "no error"); - return !!error; -} diff --git a/C/share/doc/libsoxr/examples/README b/C/share/doc/libsoxr/examples/README deleted file mode 100644 index a58939be..00000000 --- a/C/share/doc/libsoxr/examples/README +++ /dev/null @@ -1,20 +0,0 @@ -SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net - -These simple examples show the different ways that an application may -interface with soxr. Note that real-world applications may also have to -deal with file-formats, codecs, (more sophisticated) dithering, etc., which -are not covered here. - -With the library installed, the examples may be built using commands similar -to the following. On unix-like systems: - - cc 1-single-block.c -lsoxr - cc 1a-lsr.c -lsoxr-lsr - -or, with MSVC on MS-Windows: - - cl 1-single-block.c -I"C:/Program Files/soxr/include" "C:/Program Files/soxr/lib/soxr.lib" - cl 1a-lsr.c -I"C:/Program Files/soxr/include" "C:/Program Files/soxr/lib/soxr-lsr.lib" - -IDEs may hide such commands behind configuration screens and build menus -- -where applicable, consult your IDE's user-manual. diff --git a/C/share/doc/libsoxr/examples/examples-common.h b/C/share/doc/libsoxr/examples/examples-common.h deleted file mode 100644 index fc8ed82e..00000000 --- a/C/share/doc/libsoxr/examples/examples-common.h +++ /dev/null @@ -1,47 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-18 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -/* Common includes etc. for the examples. */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef _WIN32 - /* Work-around for broken file-I/O on MS-Windows: */ - #include - #include - #define USE_STD_STDIO _setmode(_fileno(stdout), _O_BINARY), \ - _setmode(_fileno(stdin ), _O_BINARY) -#else - #define USE_STD_STDIO -#endif - -#undef int16_t -#define int16_t short - -#undef int32_t -#if LONG_MAX > 2147483647L - #define int32_t int -#elif LONG_MAX < 2147483647L - #error this programme requires that 'long int' has at least 32-bits -#else - #define int32_t long -#endif - -#undef min -#define min(x,y) ((x)<(y)?(x):(y)) - -#undef max -#define max(x,y) ((x)>(y)?(x):(y)) - -#undef AL -#define AL(a) (sizeof(a)/sizeof((a)[0])) /* Array Length */ - -#undef M_PI /* Sometimes missing, so ensure that it is defined: */ -#define M_PI 3.14159265358979323846 diff --git a/C/src/soxr-0.1.3/AUTHORS b/C/src/soxr-0.1.3/AUTHORS deleted file mode 100644 index 2ba76d3a..00000000 --- a/C/src/soxr-0.1.3/AUTHORS +++ /dev/null @@ -1 +0,0 @@ -Rob Sykes diff --git a/C/src/soxr-0.1.3/CMakeLists.txt b/C/src/soxr-0.1.3/CMakeLists.txt deleted file mode 100644 index ee48f6c2..00000000 --- a/C/src/soxr-0.1.3/CMakeLists.txt +++ /dev/null @@ -1,335 +0,0 @@ -# SoX Resampler Library Copyright (c) 2007-18 robs@users.sourceforge.net -# Licence for this file: LGPL v2.1 See LICENCE for details. - -cmake_minimum_required (VERSION 3.1 FATAL_ERROR) - -project (soxr C) -set (DESCRIPTION_SUMMARY - "High quality, one-dimensional sample-rate conversion library") - - - -# Release versioning: - -set (PROJECT_VERSION_MAJOR 0) -set (PROJECT_VERSION_MINOR 1) -set (PROJECT_VERSION_PATCH 3) - -# For shared-object; if, since the last public release: -# 1) library code changed at all: ++revision -# 2) interfaces changed at all: ++current, revision = 0 -# 3) interfaces added: ++age -# 4) interfaces removed: age = 0 - -set (SO_VERSION_CURRENT 1) -set (SO_VERSION_REVISION 2) -set (SO_VERSION_AGE 1) - -math (EXPR SO_VERSION_MAJOR "${SO_VERSION_CURRENT} - ${SO_VERSION_AGE}") -math (EXPR SO_VERSION_MINOR "${SO_VERSION_AGE}") -math (EXPR SO_VERSION_PATCH "${SO_VERSION_REVISION}") - - - -# Main options: - -include (CMakeDependentOption) - -if (NOT CMAKE_BUILD_TYPE) - set (CMAKE_BUILD_TYPE Release CACHE STRING - "Build type, one of: None Debug Release RelWithDebInfo MinSizeRel." FORCE) -endif () - -option (BUILD_TESTS "Build sanity-tests." ON) -option (BUILD_EXAMPLES "Build examples." OFF) -option (WITH_OPENMP "Include OpenMP threading." ON) -option (WITH_LSR_BINDINGS "Include a `libsamplerate'-like interface." ON) - -cmake_dependent_option (BUILD_SHARED_LIBS - "Build shared (dynamic) soxr libraries." ON - "NOT WITH_DEV_GPROF" OFF) -cmake_dependent_option (WITH_VR32 - "Include HQ variable-rate resampling engine." ON - "WITH_CR32 OR WITH_CR64 OR WITH_CR32S OR WITH_CR64S OR NOT DEFINED WITH_VR32" ON) -cmake_dependent_option (WITH_CR32 - "Include HQ constant-rate resampling engine." ON - "WITH_VR32 OR WITH_CR64 OR WITH_CR32S OR WITH_CR64S" ON) -cmake_dependent_option (WITH_CR64 - "Include VHQ constant-rate resampling engine." ON - "WITH_VR32 OR WITH_CR32 OR WITH_CR32S OR WITH_CR64S" ON) -cmake_dependent_option (WITH_CR64S - "Include VHQ SIMD constant-rate resampling engine." ON - "WITH_VR32 OR WITH_CR32 OR WITH_CR32S OR WITH_CR64" ON) -cmake_dependent_option (WITH_CR32S - "Include HQ SIMD constant-rate resampling engine." ON - "WITH_VR32 OR WITH_CR64 OR WITH_CR32 OR WITH_CR64S" ON) -cmake_dependent_option (WITH_PFFFT - "Use PFFFT (BSD-like licence) for HQ SIMD DFT." ON - "WITH_CR32S;NOT WITH_AVFFT" OFF) -cmake_dependent_option (WITH_AVFFT - "Use libavcodec (LGPL) for HQ SIMD DFT." OFF - "WITH_CR32S;NOT WITH_PFFFT" OFF) -cmake_dependent_option (BUILD_LSR_TESTS "Build LSR tests." OFF - "UNIX;NOT CMAKE_CROSSCOMPILING;EXISTS ${PROJECT_SOURCE_DIR}/lsr-tests;WITH_LSR_BINDINGS" OFF) - -option (WITH_HI_PREC_CLOCK "Enable high-precision time-base." ON) -option (WITH_FLOAT_STD_PREC_CLOCK - "Use floating-point for standard-precision time-base." OFF) -option (WITH_DEV_TRACE "Enable developer trace capability." ON) -option (WITH_DEV_GPROF "Enable developer grpof output." OFF) -mark_as_advanced (WITH_HI_PREC_CLOCK WITH_FLOAT_STD_PREC_CLOCK - WITH_DEV_TRACE WITH_DEV_GPROF) - - - -# Introspection: - -list (APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules) - -include (CheckFunctionExists) -include (CheckIncludeFiles) -include (CheckLibraryExists) -include (SetSystemProcessor) -include (TestBigEndian) - -set_system_processor () - -check_library_exists (m pow "" NEED_LIBM) -if (NEED_LIBM) - set (CMAKE_REQUIRED_LIBRARIES "m;${CMAKE_REQUIRED_LIBRARIES}") - set (LIBM_LIBRARIES m) -endif () - -if (${BUILD_EXAMPLES}) - project (${PROJECT_NAME}) # Adds c++ compiler -endif () - -if (WITH_OPENMP) - find_package (OpenMP) - if (OPENMP_FOUND) - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") - if (MINGW) # Is this still needed? - set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_C_FLAGS}") - set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${OpenMP_C_FLAGS}") - endif () - endif() -endif () - -if (WITH_CR32S) - find_package (SIMD32) - set (WITH_CR32S ${SIMD32_FOUND}) -endif () - -if (WITH_CR64S) - find_package (SIMD64) - set (WITH_CR64S ${SIMD64_FOUND}) -endif () - -if (WITH_AVFFT) - find_package (LibAVCodec REQUIRED) - if (AVCODEC_FOUND) - include_directories (${AVCODEC_INCLUDE_DIRS}) - set (LIBS ${LIBS} ${AVCODEC_LIBRARIES}) - endif () -endif () - -if (WITH_AVFFT OR (CMAKE_SYSTEM_PROCESSOR MATCHES "^arm" AND SIMD32_FOUND AND WITH_CR32)) - find_package (LibAVUtil) - if (AVUTIL_FOUND) - include_directories (${AVUTIL_INCLUDE_DIRS}) - set (LIBS ${LIBS} ${AVUTIL_LIBRARIES}) - endif () -endif () - -check_function_exists (lrint HAVE_LRINT) -check_include_files (fenv.h HAVE_FENV_H) -check_include_files (stdbool.h HAVE_STDBOOL_H) -check_include_files (stdint.h HAVE_STDINT_H) -test_big_endian (HAVE_BIGENDIAN) - - - -# Compiler configuration: - -if (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") - set (PROJECT_CXX_FLAGS "${PROJECT_CXX_FLAGS} -Wconversion -Wall -Wextra \ - -pedantic -Wundef -Wpointer-arith -Wno-long-long") - if (CMAKE_C_COMPILER_ID STREQUAL "Clang") - set (PROJECT_CXX_FLAGS "${PROJECT_CXX_FLAGS} -Wno-keyword-macro") - endif () - if (WITH_DEV_GPROF) - set (PROJECT_CXX_FLAGS "${PROJECT_CXX_FLAGS} -pg") - endif () - # Can use std=c89, but gnu89 should give faster sinf, cosf, etc.: - set (PROJECT_C_FLAGS "${PROJECT_CXX_FLAGS} \ - -std=gnu89 -Wnested-externs -Wmissing-prototypes -Wstrict-prototypes") - if (CMAKE_BUILD_TYPE STREQUAL "Release") - set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -s") # strip - endif () - cmake_dependent_option (VISIBILITY_HIDDEN - "Build shared libraries with -fvisibility=hidden." ON - "BUILD_SHARED_LIBS" OFF) - mark_as_advanced (VISIBILITY_HIDDEN) - if (VISIBILITY_HIDDEN) - add_definitions (-fvisibility=hidden -DSOXR_VISIBILITY) - endif () -endif () - -if (MSVC) - add_definitions (-D_USE_MATH_DEFINES -D_CRT_SECURE_NO_WARNINGS) - option (BUILD_SHARED_RUNTIME "MSVC, link with runtime dynamically." ON) - if (NOT BUILD_SHARED_RUNTIME) - foreach (flag_var - CMAKE_C_FLAGS CMAKE_CXX_FLAGS - CMAKE_C_FLAGS_DEBUG CMAKE_CXX_FLAGS_DEBUG - CMAKE_C_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELEASE - CMAKE_C_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_MINSIZEREL - CMAKE_C_FLAGS_RELWITHDEBINFO CMAKE_CXX_FLAGS_RELWITHDEBINFO) - string (REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") - endforeach () - endif () - # By default, do not warn when built on machines using only VS Express: - if (NOT DEFINED CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS) - set (CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS ON) - endif () -endif () - - - -# Build configuration: - -if (${BUILD_SHARED_LIBS} AND ${CMAKE_SYSTEM_NAME} STREQUAL Windows) - # Allow exes to find dlls: - set (BIN ${PROJECT_BINARY_DIR}/bin/) - set (EXAMPLES_BIN ${BIN}) - set (CMAKE_LIBRARY_OUTPUT_DIRECTORY ${BIN}) - set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${BIN}) -else () - set (BIN ./) - set (EXAMPLES_BIN ../examples/) -endif () - -set (LIB_TYPE STATIC) -if (BUILD_SHARED_LIBS) - set (LIB_TYPE SHARED) - if (MSVC) - add_definitions (-DSOXR_DLL) - endif () -endif () - -if (CMAKE_BUILD_TYPE STREQUAL "None") # As used by some distros. - add_definitions (-DNDEBUG) -endif () - - - -# Installation configuration: - -if (NOT DEFINED BIN_INSTALL_DIR) - set (BIN_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/bin") -endif () -if (NOT DEFINED LIB_INSTALL_DIR) - set (LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}") -endif () -if (NOT DEFINED INCLUDE_INSTALL_DIR) - set (INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/include") -endif () -if (NOT DEFINED DOC_INSTALL_DIR) - if (UNIX) - set (DOC_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/share/doc/lib${PROJECT_NAME}") - else () - set (DOC_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/doc") - endif () -endif () - -if (APPLE) - option (BUILD_FRAMEWORK "Build an OS X framework." OFF) - set (FRAMEWORK_INSTALL_DIR - "/Library/Frameworks" CACHE STRING "Directory to install frameworks to.") -endif () - - - -# Top-level: - -set (PROJECT_VERSION - ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}) -set (SO_VERSION ${SO_VERSION_MAJOR}.${SO_VERSION_MINOR}.${SO_VERSION_PATCH}) - -configure_file ( - ${PROJECT_SOURCE_DIR}/${PROJECT_NAME}-config.h.in - ${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.h) -include_directories (${PROJECT_BINARY_DIR}) - -if (NOT CMAKE_CROSSCOMPILING AND (BUILD_TESTS OR BUILD_LSR_TESTS)) - enable_testing () -endif () - -install (FILES - ${CMAKE_CURRENT_SOURCE_DIR}/README - ${CMAKE_CURRENT_SOURCE_DIR}/LICENCE - ${CMAKE_CURRENT_SOURCE_DIR}/NEWS - DESTINATION ${DOC_INSTALL_DIR}) - - - -# Subdirectories: - -include_directories (${PROJECT_SOURCE_DIR}/src) - -add_subdirectory (src) -if (BUILD_TESTS) - add_subdirectory (tests) -endif () -if (BUILD_LSR_TESTS) - add_subdirectory (lsr-tests) -endif () -if (BUILD_EXAMPLES OR BUILD_TESTS) - add_subdirectory (examples) -endif () - - - -# GNU Autotools compatibility; 'make check': - -add_custom_target (check COMMAND ${CMAKE_CTEST_COMMAND}) - - - -# GNU Autotools compatibility; 'make distclean': - -if (UNIX) - add_custom_target (distclean COMMAND make clean && find . - \\! -path \\*/Modules/\\* \\! -name cmp-test.cmake -a -name \\*.cmake - -o -name CMakeFiles -o -name Makefile -o -name CMakeCache.txt -o -name - Testing -o -name cmake_install.cmake -o -name install_manifest.txt -o - -path ./soxr-config.h -o -name config.h -o -name \\*.pc -o -name \\*.s32 - | xargs rm -rf) -endif () - - - -# Deinstallation: - -configure_file ( - "${CMAKE_CURRENT_SOURCE_DIR}/deinstall.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/deinstall.cmake" - IMMEDIATE @ONLY) - -add_custom_target (deinstall - COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_BINARY_DIR}/deinstall.cmake") - - - -# Packaging: - -if (UNIX) - set (CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}") - set (CPACK_PACKAGE_VERSION_MINOR "${PROJECT_VERSION_MINOR}") - set (CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}") - set (CPACK_SOURCE_GENERATOR "TXZ") - set (CPACK_SOURCE_IGNORE_FILES - "dist;/lsr-tests/;/Debug.*/;/Release.*/;\\\\.swp$;\\\\.git.*;/\\\\.git/") - include (CPack) -endif () diff --git a/C/src/soxr-0.1.3/COPYING.LGPL b/C/src/soxr-0.1.3/COPYING.LGPL deleted file mode 100644 index 551cb4ac..00000000 --- a/C/src/soxr-0.1.3/COPYING.LGPL +++ /dev/null @@ -1,502 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! diff --git a/C/src/soxr-0.1.3/INSTALL b/C/src/soxr-0.1.3/INSTALL deleted file mode 100644 index 5599870a..00000000 --- a/C/src/soxr-0.1.3/INSTALL +++ /dev/null @@ -1,183 +0,0 @@ -SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net - -INSTALLATION GUIDE CONTENTS - -* Standard build -* Build customisation -* Cross-compilation -* Integration with other build systems -* Run-time configuration - - - -STANDARD BUILD - -1. Prerequisites: - - Before you can build this library, you need to have available on your - system: - - * A C-compiler with 64-bit integer support and, optionally, OpenMP, SIMD. - - * A 'make' utility (most compiler installations already have one of these). - - * CMake v3.0 or newer: https://cmake.org/download/ - - -2. Build: - - At a command prompt, change directory (`cd') to the one containing this - file, then enter: - - go (on MS-Windows with nmake) - or - ./go (on Unix-like systems) - - This should build the library and run a few sanity tests. - - -3. Installation: - - Note that this step may need to be performed by a system - administrator. Enter: - - nmake install (on MS-Windows) - or - cd Release; make install (on Unix-like) - - -4. Preparation for use: - - To use the library you may need to set up appropriate paths to the - library and its header file in your development environment. - - -5. Installation test - - To test the installation, build and run some of the example programmes - (see examples/README). - - - -BUILD CUSTOMISATION - -If it is necessary to customise the build, then steps 2 and 3 above should be -substituted as follows: change directory to the one containing this file, then -enter commands along the lines: - - mkdir build - cd build - cmake -Wno-dev -DCMAKE_BUILD_TYPE=Release [OPTIONS] .. - make - make test - sudo make install - -N.B. The CMAKE_BUILD_TYPE to use for library deployment is Release. - -To list help on the available options, enter: - - cmake -LH .. - -Options, if given, should be preceded with '-D', e.g. - - -DBUILD_SHARED_LIBS:BOOL=OFF - - - -Resampling engines - -As available on a given system, options for including up-to five resampling -‘engines’ are available (per above) as follows: - - WITH_CR32: for constant-rate HQ resampling, - WITH_CR32S: SIMD variant of previous, - WITH_CR64: for constant-rate VHQ resampling, - WITH_CR64S: SIMD variant of previous, - WITH_VR32: for variable-rate HQ resampling. - -By default, these options are all set to ON. - -When both SIMD and non-SIMD engine variants are included, run-time selection -is automatic (based on CPU capability) for x86 CPUs, and can be automatic for -ARM CPUs if the 3rd-party library `libavutil' is available at libsoxr -build-time. Which engine has been selected for a specific configuration and -invocation of the library can be checked using example #3, which reports it. -See also Run-time Configuration, below. - - - -CROSS-COMPILATION - -E.g. targeting a Linux ARM system: - - mkdir build - cd build - cmake -DCMAKE_SYSTEM_NAME=Linux \ - -DCMAKE_C_COMPILER=arm-linux-gnueabi-gcc \ - .. -or, also building the examples (one of which uses C++): - - cmake -DCMAKE_SYSTEM_NAME=Linux \ - -DCMAKE_C_COMPILER=arm-linux-gnueabi-gcc \ - -DCMAKE_CXX_COMPILER=arm-linux-gnueabi-g++ \ - -DBUILD_EXAMPLES=1 \ - .. - -E.g. with Mingw (Linux host), using a tool-chain file: - - mkdir build - cd build - cmake -DCMAKE_TOOLCHAIN_FILE=~/Toolchain-x86_64-mingw-w64-mingw32.cmake \ - -DCMAKE_INSTALL_PREFIX=install \ - .. - make - -where ~/Toolchain-x86_64-mingw-w64-mingw32.cmake might contain: - - SET(CMAKE_SYSTEM_NAME Windows) - SET(CMAKE_C_COMPILER /usr/bin/x86_64-w64-mingw32-gcc) - SET(CMAKE_CXX_COMPILER /usr/bin/x86_64-w64-mingw32-g++) - SET(CMAKE_RC_COMPILER /usr/bin/x86_64-w64-mingw32-windres) - SET(CMAKE_Fortran_COMPILER /usr/bin/x86_64-w64-mingw32-gfortran) - SET(CMAKE_AR:FILEPATH /usr/bin/x86_64-w64-mingw32-ar) - SET(CMAKE_RANLIB:FILEPATH /usr/bin/x86_64-w64-mingw32-ranlib) - SET(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32) - SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) - SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) - SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) - SET(QT_BINARY_DIR /usr/x86_64-w64-mingw32/bin /usr/bin) - SET(Boost_COMPILER -gcc47) - - - -INTEGRATION WITH OTHER BUILD SYSTEMS - -Autotools-based systems might find it useful to create a file called -`configure' in the directory containing this file, consisting of the line: - cmake -DBUILD_SHARED_LIBS=OFF . -(or with other build options as required). - -For MS Visual Studio, see msvc/README. - - - -RUN-TIME CONFIGURATION - -The libsoxr API structure ‘soxr_runtime_spec_t’ allows application developers -to optimise some aspects of libsoxr’s operation for a particular application. -Optimal performance however, might depend on an individual end-user’s run- -time system and the end-user’s preferences. Hence environment variables are -available to set (override) run-time parameters as follows: - - Env. variable Equivalent soxr_runtime_spec_t item (see soxr.h) - ------------------ ----------------------------------- - SOXR_COEFS_SIZE coef_size_kbytes - SOXR_COEF_INTERP SOXR_COEF_INTERP_xxx - SOXR_LARGE_DFT_SIZE log2_large_dft_size - SOXR_MIN_DFT_SIZE log2_min_dft_size - SOXR_NUM_THREADS num_threads - -Additionally, the SOXR_USE_SIMD32 and SOXR_USE_SIMD64 boolean environment -variables can be used to override automatic selection (or to provide manual -selection where automatic selection is not available) between SIMD and -non-SIMD engine variants. diff --git a/C/src/soxr-0.1.3/LICENCE b/C/src/soxr-0.1.3/LICENCE deleted file mode 100644 index 43e5a716..00000000 --- a/C/src/soxr-0.1.3/LICENCE +++ /dev/null @@ -1,23 +0,0 @@ -SoX Resampler Library Copyright (c) 2007-18 robs@users.sourceforge.net - -This library is free software; you can redistribute it and/or modify it -under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation; either version 2.1 of the License, or (at -your option) any later version. - -This library is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser -General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with this library; if not, see . - - -Notes - -1. Re software in the `examples' directory: works that are not resampling -examples but are based on the given examples -- for example, applications using -the library -- shall not be considered to be derivative works of the examples. - -2. If building with pffft.c, see the licence embedded in that file. diff --git a/C/src/soxr-0.1.3/NEWS b/C/src/soxr-0.1.3/NEWS deleted file mode 100644 index 9e7c298f..00000000 --- a/C/src/soxr-0.1.3/NEWS +++ /dev/null @@ -1,46 +0,0 @@ -Version 0.1.3 (2018-02-24) - * SIMD enhancements: SSE, AVX, Neon. - * Improve support for clang, ARM, and cross-compilation. - * Provide env. var. override of runtime parameters. - * Build fix re cmake variables AVCODEC_INCLUDE_DIRS & AVUTIL_INCLUDE_DIRS. - * Build options WITH_SINGLE_PRECISION, WITH_DOUBLE_PRECISION & WITH_SIMD have - been removed; replacement options are detailed in INSTALL, `Resampling - engines'. - -Version 0.1.2 (2015-09-05) - * Fix conversion failure when I/O types differ but I/O rates don't. - * Fix #defines for interpolation order selection. - * Fix ineffectual SOXR_MINIMUM_PHASE and SOXR_INTERMEDIATE_PHASE in - soxr_quality_spec recipe. - * Fix soxr_delay() returning a negative number after end-of-input has been - indicated. - * Fix crash when using soxr_process() after calling soxr_clear(). - * Be more POSIX compliant w.r.t. errno in the examples; fixes erroneous - reporting of errors on FreeBSD. - * Quality improvement for variable-rate. - * Various fixes/improvements to build/tests/documentation. - -Version 0.1.1 (2013-03-03) - * Minor fixes/improvements to build/tests. - * Fix crash (e.g. with k3b) when null error pointer passed to src_create (lsr - bindings only). - * Fix broken resampling in many cases with SIMD and anti_aliasing_pc < 100. - * For clarity, renamed and slightly changed usage of three parameters in - soxr_quality_spec_t (ABI compatible, API incompatible). An application not - setting these parameters directly need make no change; otherwise, changes - should be made per the following example (as shown, compatibility with both - old/new APIs is maintained). See also the comments on these parameters in - soxr.h. N.B. ABI compatibility with the 0.1.0 API may be removed in a - future release. - #if !defined SOXR_VERSION /* Deprecated, 0.1.0 API */ - q_spec.phase = minimum_phase? 0 : 50; - q_spec.bw_pc = cutoff * 100; - q_spec.anti_aliasing_pc = anti_aliasing * 100; - #else /* 0.1.1 API */ Explanation: - q_spec.phase_response = minimum_phase? 0 : 50; Renamed. - q_spec.passband_end = cutoff; Renamed, no longer %. - q_spec.stopband_begin = 2 - anti_aliasing; Renamed, no longer %, no - #endif longer mirrored in Fs. - -Version 0.1.0 (2013-01-19) - * First public release. diff --git a/C/src/soxr-0.1.3/README b/C/src/soxr-0.1.3/README deleted file mode 100644 index 7f9a7afb..00000000 --- a/C/src/soxr-0.1.3/README +++ /dev/null @@ -1,53 +0,0 @@ -SoX Resampler Library Copyright (c) 2007-18 robs@users.sourceforge.net - -The SoX Resampler library `libsoxr' performs one-dimensional sample-rate -conversion -- it may be used, for example, to resample PCM-encoded audio. -For higher-dimensional resampling, such as for visual-image processing, you -should look elsewhere. - -It aims to give fast¹ and very high quality² results for any constant -(rational or irrational) resampling ratio. Phase-response, preserved -bandwidth, aliasing, and rejection level parameters are all configurable; -alternatively, simple `preset' configurations may be selected. A -variable-rate resampling mode of operation is also included. - -The resampler is currently available either as part of `libsox' (the audio -file-format and effect library), or stand-alone as `libsoxr' (this package). -The interfaces to libsox and libsoxr are slightly different, with that of -libsoxr designed specifically for resampling. An application requiring -support for other effects, or for reading-from or writing-to audio files or -devices, should use libsox (or other libraries such as libsndfile or -libavformat). - -Libsoxr provides a simple API that allows interfacing using the most -commonly-used sample formats and buffering schemes: sample-formats may be -either floating-point or integer, and multiple channels either interleaved -or split in separate buffers. The API is documented in the header file -`soxr.h', together with sample code found in the 'examples' directory. - -For compatibility with the popular `libsamplerate' library, the header file -`soxr-lsr.h' is provided and may be used as an alternative API.³ Note -however, that libsoxr does not provide a full emulation of libsamplerate -and that using this approach, only a sub-set of libsoxr's features are -available. - -The design was inspired by Laurent De Soras' paper `The Quest For The -Perfect Resampler', http://ldesoras.free.fr/doc/articles/resampler-en.pdf; -in essence, it combines Julius O. Smith's `Bandlimited Interpolation' -technique (https://ccrma.stanford.edu/~jos/resample/resample.pdf) with FFT- -based over-sampling. - -Note that for real-time resampling, libsoxr may have a higher latency -than non-FFT based resamplers. For example, when using the `High Quality' -configuration to resample between 44100Hz and 48000Hz, the latency is -around 1000 output samples, i.e. roughly 20ms (though passband and FFT- -size configuration parameters may be used to reduce this figure). - -For build and installation instructions, see the file `INSTALL'; for -copyright and licensing information, see the file `LICENCE'. - -For support and new versions, see https://soxr.sourceforge.net -________ -¹ For example, multi-channel resampling can utilise multiple CPU-cores. -² Bit-perfect within practical occupied-bandwidth limits. -³ For details of that API, see http://www.mega-nerd.com/SRC/api.html. diff --git a/C/src/soxr-0.1.3/TODO b/C/src/soxr-0.1.3/TODO deleted file mode 100644 index 2d1bc192..00000000 --- a/C/src/soxr-0.1.3/TODO +++ /dev/null @@ -1,3 +0,0 @@ -* vr32s -* vr32 with 1-delay-clear -* fir_to_phase with RDFT32 diff --git a/C/src/soxr-0.1.3/cmake/Modules/FindCFlags.cmake b/C/src/soxr-0.1.3/cmake/Modules/FindCFlags.cmake deleted file mode 100644 index f1187275..00000000 --- a/C/src/soxr-0.1.3/cmake/Modules/FindCFlags.cmake +++ /dev/null @@ -1,35 +0,0 @@ -# SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net -# Licence for this file: LGPL v2.1 See LICENCE for details. - -# - Function to find C compiler feature flags - -include (CheckCSourceCompiles) -include (FindPackageHandleStandardArgs) - -function (FindCFlags PKG_NAME PKG_DESC TRIAL_C_FLAGS TEST_C_SOURCE) - -foreach (TRIAL_C_FLAG ${TRIAL_C_FLAGS}) - message (STATUS "Trying ${PKG_NAME} C flags: ${TRIAL_C_FLAG}") - unset (DETECT_${PKG_NAME}_C_FLAGS CACHE) #displayed by check_c_source_compiles - - set (TMP "${CMAKE_REQUIRED_FLAGS}") - set (CMAKE_REQUIRED_FLAGS "${TRIAL_C_FLAG}") - check_c_source_compiles ("${TEST_C_SOURCE}" DETECT_${PKG_NAME}_C_FLAGS) - set (CMAKE_REQUIRED_FLAGS "${TMP}") - - if (DETECT_${PKG_NAME}_C_FLAGS) - set (DETECTED_C_FLAGS "${TRIAL_C_FLAG}") - break () - endif () -endforeach () - -# N.B. Will not overwrite existing cache variable: -set (${PKG_NAME}_C_FLAGS "${DETECTED_C_FLAGS}" - CACHE STRING "C compiler flags for ${PKG_DESC}") - -find_package_handle_standard_args ( - ${PKG_NAME} DEFAULT_MSG ${PKG_NAME}_C_FLAGS ${PKG_NAME}_C_FLAGS) -mark_as_advanced (${PKG_NAME}_C_FLAGS) -set (${PKG_NAME}_FOUND ${${PKG_NAME}_FOUND} PARENT_SCOPE) - -endfunction () diff --git a/C/src/soxr-0.1.3/cmake/Modules/FindLibAVCodec.cmake b/C/src/soxr-0.1.3/cmake/Modules/FindLibAVCodec.cmake deleted file mode 100644 index f1bbf89a..00000000 --- a/C/src/soxr-0.1.3/cmake/Modules/FindLibAVCodec.cmake +++ /dev/null @@ -1,23 +0,0 @@ -# SoX Resampler Library Copyright (c) 2007-18 robs@users.sourceforge.net -# Licence for this file: LGPL v2.1 See LICENCE for details. - -# - Find AVCODEC -# Find the installation of this package: include-dirs and libraries. -# -# AVCODEC_INCLUDE_DIRS - where to find headers for this package. -# AVCODEC_LIBRARIES - libraries to link to when using this package. -# AVCODEC_FOUND - true iff this package can be found. - -if (AVCODEC_INCLUDE_DIRS) - set (AVCODEC_FIND_QUIETLY TRUE) -endif () - -find_path (AVCODEC_INCLUDE_DIRS libavcodec/avcodec.h) - -find_library (AVCODEC_LIBRARIES NAMES avcodec) - -include (FindPackageHandleStandardArgs) -find_package_handle_standard_args ( - AVCODEC DEFAULT_MSG AVCODEC_LIBRARIES AVCODEC_INCLUDE_DIRS) - -mark_as_advanced (AVCODEC_LIBRARIES AVCODEC_INCLUDE_DIRS) diff --git a/C/src/soxr-0.1.3/cmake/Modules/FindLibAVUtil.cmake b/C/src/soxr-0.1.3/cmake/Modules/FindLibAVUtil.cmake deleted file mode 100644 index 464e6cf4..00000000 --- a/C/src/soxr-0.1.3/cmake/Modules/FindLibAVUtil.cmake +++ /dev/null @@ -1,23 +0,0 @@ -# SoX Resampler Library Copyright (c) 2007-18 robs@users.sourceforge.net -# Licence for this file: LGPL v2.1 See LICENCE for details. - -# - Find AVUTIL -# Find the installation of this package: includes and libraries. -# -# AVUTIL_INCLUDE_DIRS - where to find headers for this package. -# AVUTIL_LIBRARIES - libraries to link to when using this package. -# AVUTIL_FOUND - true iff this package can be found. - -if (AVUTIL_INCLUDE_DIRS) - set (AVUTIL_FIND_QUIETLY TRUE) -endif () - -find_path (AVUTIL_INCLUDE_DIRS libavutil/cpu.h) - -find_library (AVUTIL_LIBRARIES NAMES avutil) - -include (FindPackageHandleStandardArgs) -find_package_handle_standard_args ( - AVUTIL DEFAULT_MSG AVUTIL_LIBRARIES AVUTIL_INCLUDE_DIRS) - -mark_as_advanced (AVUTIL_LIBRARIES AVUTIL_INCLUDE_DIRS) diff --git a/C/src/soxr-0.1.3/cmake/Modules/FindSIMD32.cmake b/C/src/soxr-0.1.3/cmake/Modules/FindSIMD32.cmake deleted file mode 100644 index 9e423735..00000000 --- a/C/src/soxr-0.1.3/cmake/Modules/FindSIMD32.cmake +++ /dev/null @@ -1,54 +0,0 @@ -# SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net -# Licence for this file: LGPL v2.1 See LICENCE for details. - -# - Finds SIMD32 support -# -# The following variables are set: -# SIMD32_C_FLAGS - flags to add to the C compiler for this package. -# SIMD32_FOUND - true if support for this package is found. - -if (DEFINED SIMD32_C_FLAGS) - set (TRIAL_C_FLAGS) -elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "^arm") - set (TRIAL_C_FLAGS - # Gcc - "-mfpu=neon-vfpv4 -mcpu=cortex-a7" - "-mfpu=neon -mfloat-abi=hard" - "-mfpu=neon -mfloat-abi=softfp" - "-mfpu=neon -mfloat-abi=soft" - ) - set (TEST_C_SOURCE " - #include - int main(int c, char * * v) { - float32x4_t a = vdupq_n_f32((float)c), b = vdupq_n_f32((float)!!v); - return !vgetq_lane_u32(vceqq_f32(a,b),0); - } - ") -else () - if (WIN32) # Safety for when mixed lib/app compilers (but performance hit) - set (GCC_WIN32_SIMD32_OPTS "-mincoming-stack-boundary=2") - endif () - - set (TRIAL_C_FLAGS - # x64 - " " - # MSVC x86 - "/arch:SSE /fp:fast -D__SSE__" - # Gcc x86 - "-msse -mfpmath=sse ${GCC_WIN32_SIMD32_OPTS}" - # Gcc x86 (old versions) - "-msse -mfpmath=sse" - ) - set (TEST_C_SOURCE " - #include - int main(int c, char * * v) { - __m128 a = _mm_set_ss((float)c), b = _mm_set_ss((float)!!v); - return _mm_comineq_ss(a,b); - } - ") -endif () - -include (FindCFlags) - -FindCFlags ("SIMD32" "FLOAT-32 (single-precision) SIMD vectorization" - "${TRIAL_C_FLAGS}" "${TEST_C_SOURCE}") diff --git a/C/src/soxr-0.1.3/cmake/Modules/FindSIMD64.cmake b/C/src/soxr-0.1.3/cmake/Modules/FindSIMD64.cmake deleted file mode 100644 index d4126443..00000000 --- a/C/src/soxr-0.1.3/cmake/Modules/FindSIMD64.cmake +++ /dev/null @@ -1,29 +0,0 @@ -# SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net -# Licence for this file: LGPL v2.1 See LICENCE for details. - -# - Finds SIMD64 support -# -# The following variables are set: -# SIMD64_C_FLAGS - flags to add to the C compiler for this package. -# SIMD64_FOUND - true if support for this package is found. - -if (DEFINED SIMD64_C_FLAGS OR CMAKE_SYSTEM_PROCESSOR MATCHES "^arm") - set (TRIAL_C_FLAGS) -else () - set (TRIAL_C_FLAGS - "-mavx" # Gcc - "/arch:AVX" # MSVC - ) - set (TEST_C_SOURCE " - #ifndef __AVX__ - #error - #endif - #include - int main() {return 0;} - ") -endif () - -include (FindCFlags) - -FindCFlags ("SIMD64" "FLOAT-64 (double-precision) SIMD vectorization" - "${TRIAL_C_FLAGS}" "${TEST_C_SOURCE}") diff --git a/C/src/soxr-0.1.3/cmake/Modules/SetSystemProcessor.cmake b/C/src/soxr-0.1.3/cmake/Modules/SetSystemProcessor.cmake deleted file mode 100644 index 8e2c2921..00000000 --- a/C/src/soxr-0.1.3/cmake/Modules/SetSystemProcessor.cmake +++ /dev/null @@ -1,37 +0,0 @@ -# SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net -# Licence for this file: LGPL v2.1 See LICENCE for details. - -# Sets CMAKE_SYSTEM_PROCESSOR for cross-compiling. - -macro (set_system_processor) - if (CMAKE_CROSSCOMPILING) - if ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "" OR "${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "unknown") - unset(CMAKE_SYSTEM_PROCESSOR) - endif () - if (NOT DEFINED CMAKE_SYSTEM_PROCESSOR) - include (CheckCSourceCompiles) - set (CPU_LINES - "#if defined __x86_64__ || defined _M_X64 /*\;x86_64\;*/" - "#if defined __i386__ || defined _M_IX86 /*\;x86_32\;*/" - "#if defined __arm__ || defined _M_ARM /*\;arm\;*/" - ) - foreach (CPU_LINE ${CPU_LINES}) - string (CONCAT CPU_SOURCE "${CPU_LINE}" " - int main() {return 0;} - #endif - ") - unset (SYSTEM_PROCESSOR_DETECTED CACHE) - check_c_source_compiles ("${CPU_SOURCE}" SYSTEM_PROCESSOR_DETECTED) - if (SYSTEM_PROCESSOR_DETECTED) - list (GET CPU_LINE 1 CMAKE_SYSTEM_PROCESSOR) - message (STATUS "CMAKE_SYSTEM_PROCESSOR is ${CMAKE_SYSTEM_PROCESSOR}") - break () - endif () - endforeach () - endif () - - # N.B. Will not overwrite existing cache variable: - set (CMAKE_SYSTEM_PROCESSOR "${CMAKE_SYSTEM_PROCESSOR}" - CACHE STRING "Target system processor") - endif () -endmacro () diff --git a/C/src/soxr-0.1.3/deinstall.cmake.in b/C/src/soxr-0.1.3/deinstall.cmake.in deleted file mode 100644 index 307be501..00000000 --- a/C/src/soxr-0.1.3/deinstall.cmake.in +++ /dev/null @@ -1,25 +0,0 @@ -# SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net -# Licence for this file: LGPL v2.1 See LICENCE for details. - -if (NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") - message (FATAL_ERROR "Cannot find install manifest") -endif () - -file (READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) -string (REGEX REPLACE "\n" ";" files "${files}") -foreach (file ${files}) - set (dest "$ENV{DESTDIR}${file}") - message (STATUS "Deinstalling \"${dest}\"") - if (EXISTS "${dest}" OR IS_SYMLINK "${dest}") - execute_process ( - COMMAND "@CMAKE_COMMAND@" -E remove "${dest}" - OUTPUT_VARIABLE rm_out - RESULT_VARIABLE rm_retval - ) - if (NOT ${rm_retval} EQUAL 0) - message (FATAL_ERROR "Problem when removing \"${dest}\"") - endif () - else () - message (STATUS "File \"${dest}\" does not exist.") - endif () -endforeach () diff --git a/C/src/soxr-0.1.3/examples/1-single-block.c b/C/src/soxr-0.1.3/examples/1-single-block.c deleted file mode 100644 index 3b919b45..00000000 --- a/C/src/soxr-0.1.3/examples/1-single-block.c +++ /dev/null @@ -1,50 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -/* Example 1: `One-shot' resample a single block of data in memory. - * - * N.B. See example 2 for how to resample a stream (of blocks). - * - * Optional arguments are: INPUT-RATE OUTPUT-RATE - * - * With the default arguments, the output should produce lines similar to the - * following: - * - * 0.00 0.71 1.00 0.71 -0.00 -0.71 -1.00 -0.71 - * - * Gibbs effect may be seen at the ends of the resampled signal; this is because - * unlike a `real-world' signal, the synthetic input signal is not band-limited. - */ - -#include -#include "examples-common.h" - -const float in[] = { /* Input: 12 cycles of a sine wave with freq. = irate/4 */ - 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, - 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1}; - -int main(int argc, char const * arg[]) -{ - double irate = argc > 1? atof(arg[1]) : 1; /* Default to interpolation */ - double orate = argc > 2? atof(arg[2]) : 2; /* by a factor of 2. */ - - size_t olen = (size_t)(AL(in) * orate / irate + .5); /* Assay output len. */ - float * out = malloc(sizeof(*out) * olen); /* Allocate output buffer. */ - size_t odone; - - soxr_error_t error = soxr_oneshot(irate, orate, 1, /* Rates and # of chans. */ - in, AL(in), NULL, /* Input. */ - out, olen, &odone, /* Output. */ - NULL, NULL, NULL); /* Default configuration.*/ - - unsigned i = 0; /* Print out the resampled data, */ - while (i++ < odone) - printf("%5.2f%c", out[i-1], " \n"[!(i&7) || i == odone]); - printf("%-26s %s\n", arg[0], soxr_strerror(error)); /* and reported result. */ - - if (argc > 3) /* Library version check: */ - printf("runtime=%s API="SOXR_THIS_VERSION_STR"\n", soxr_version()); - - free(out); /* Tidy up. */ - return !!error; -} diff --git a/C/src/soxr-0.1.3/examples/1a-lsr.c b/C/src/soxr-0.1.3/examples/1a-lsr.c deleted file mode 100644 index 6b50a8f5..00000000 --- a/C/src/soxr-0.1.3/examples/1a-lsr.c +++ /dev/null @@ -1,40 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -/* Example 1a: Variant of example 1 using libsamplerate-like bindings. */ - -#include -#include "examples-common.h" - -float in[] = { /* Input: 12 cycles of a sine wave with freq. = irate/4 */ - 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, - 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1, 0,1,0,-1}; - -int main(int argc, char const * arg[]) -{ - double irate = argc > 1? atof(arg[1]) : 1; /* Default to interpolation */ - double orate = argc > 2? atof(arg[2]) : 2; /* by a factor of 2. */ - - size_t olen = (size_t)(AL(in) * orate / irate + .5); /* Assay output len. */ - float * out = (float *)malloc(sizeof(*out) * olen); /* Allocate output buf. */ - - int error, i = 0; - SRC_DATA data; - - data.data_in = in; - data.data_out = out; - data.input_frames = AL(in); - data.output_frames = (int)olen; - data.src_ratio = orate / irate; - error = src_simple(&data, SRC_SINC_FASTEST, 1); - - while (i++ < data.output_frames_gen) /* Print out the resampled data, */ - printf("%5.2f%c", out[i-1], " \n"[!(i&7) || i == data.output_frames_gen]); - printf("%-26s %s\n", arg[0], src_strerror(error)); /* and reported result. */ - - if (argc > 3) /* Library version check: */ - printf("runtime=%s\n", src_get_version()); - - free(out); /* Tidy up. */ - return !!error; -} diff --git a/C/src/soxr-0.1.3/examples/2-stream.C b/C/src/soxr-0.1.3/examples/2-stream.C deleted file mode 100644 index 29c1bf62..00000000 --- a/C/src/soxr-0.1.3/examples/2-stream.C +++ /dev/null @@ -1,78 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -/* Example 2: resample a raw, single-channel, floating-point data stream from - * stdin to stdout. - * - * The application uses the single function `soxr_process' for both input and - * output to/from the resampler; compared to the `input function' approach - * (illustrated in example 3) this requires that the application implements - * more logic, but one less function. - * - * Arguments are: INPUT-RATE OUTPUT-RATE - */ - -#include -#include "examples-common.h" - -int main(int argc, char const * arg[]) -{ - double const irate = argc > 1? atof(arg[1]) : 96000.; - double const orate = argc > 2? atof(arg[2]) : 44100.; - - /* Allocate resampling input and output buffers in proportion to the input - * and output rates: */ - #define buf_total_len 15000 /* In samples. */ - size_t const olen = (size_t)(orate * buf_total_len / (irate + orate) + .5); - size_t const ilen = buf_total_len - olen; - size_t const osize = sizeof(float), isize = osize; - void * obuf = malloc(osize * olen); - void * ibuf = malloc(isize * ilen); - - size_t odone, written, need_input = 1; - soxr_error_t error; - - /* Create a stream resampler: */ - soxr_t soxr = soxr_create( - irate, orate, 1, /* Input rate, output rate, # of channels. */ - &error, /* To report any error during creation. */ - NULL, NULL, NULL); /* Use configuration defaults.*/ - - if (!error) { /* If all is well, run the resampler: */ - USE_STD_STDIO; - /* Resample in blocks: */ - do { - size_t ilen1 = 0; - - if (need_input) { - - /* Read one block into the buffer, ready to be resampled: */ - ilen1 = fread(ibuf, isize, ilen, stdin); - - if (!ilen1) { /* If the is no (more) input data available, */ - free(ibuf); /* set ibuf to NULL, to indicate end-of-input */ - ibuf = NULL; /* to the resampler. */ - } - } - - /* Copy data from the input buffer into the resampler, and resample - * to produce as much output as is possible to the given output buffer: */ - error = soxr_process(soxr, ibuf, ilen1, NULL, obuf, olen, &odone); - - written = fwrite(obuf, osize, odone, stdout); /* Consume output.*/ - - /* If the actual amount of data output is less than that requested, and - * we have not already reached the end of the input data, then supply some - * more input next time round the loop: */ - need_input = odone < olen && ibuf; - - } while (!error && (need_input || written)); - } - /* Tidy up: */ - soxr_delete(soxr); - free(obuf), free(ibuf); - /* Diagnostics: */ - fprintf(stderr, "%-26s %s; I/O: %s\n", arg[0], soxr_strerror(error), - ferror(stdin) || ferror(stdout)? strerror(errno) : "no error"); - return !!error; -} diff --git a/C/src/soxr-0.1.3/examples/3-options-input-fn.c b/C/src/soxr-0.1.3/examples/3-options-input-fn.c deleted file mode 100644 index afd43b9f..00000000 --- a/C/src/soxr-0.1.3/examples/3-options-input-fn.c +++ /dev/null @@ -1,114 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -/* Example 3: extends example 2 with multiple channels, multiple datatypes, - * and other options. - * - * The application provides an input function, called on demand by libsoxr, in - * response to calls to soxr_output(); compared to the `process' approach - * (illustrated in example 2) this requires that the application implements - * less logic, but one more function. - * - * The 11 arguments (which are optional, from last to first) are: - * INPUT-RATE As example 2 - * OUTPUT-RATE Ditto - * NUM-CHANNELS Number of interleaved channels - * IN-DATATYPE# 0:float32 1:float64 2:int32 3:int16 - * OUT-DATATYPE# Ditto; or 11 for un-dithered int16 - * Q-RECIPE Quality recipe (in hex) See soxr.h - * Q-FLAGS Quality flags (in hex) See soxr.h - * PASSBAND-END % - * STOPBAND-BEGIN % - * PHASE-RESPONSE [0,100] - * USE-THREADS 1 to use multi-threading (where available) - */ - -#include -#include "examples-common.h" - -typedef struct {void * ibuf; size_t isize;} input_context_t; - -static size_t input_fn(input_context_t * p, soxr_cbuf_t * buf, size_t len) -{ - /* Read one block into the buffer, ready to be input to the resampler: */ - len = fread(p->ibuf, p->isize, len, stdin); /* Actual len read may be less. */ - - /* Inform the resampler of the data's whereabouts (which could be anywhere, in - * a freshly malloc'd buffer, for example): */ - *buf = (!len && ferror(stdin))? NULL : p->ibuf; /* NULL if error occurred. */ - - return len; /* # of samples per channel to input. */ -} - -int main(int n, char const * arg[]) -{ - char const * const arg0 = n? --n, *arg++ : "", * engine = ""; - double const irate = n? --n, atof(*arg++) : 96000.; - double const orate = n? --n, atof(*arg++) : 44100.; - unsigned const chans = n? --n, (unsigned)atoi(*arg++) : 1; - soxr_datatype_t const itype = n? --n, (soxr_datatype_t)atoi(*arg++) : 0; - unsigned const ospec = n? --n, (soxr_datatype_t)atoi(*arg++) : 0; - unsigned long const q_recipe= n? --n, strtoul(*arg++, 0, 16) : SOXR_HQ; - unsigned long const q_flags = n? --n, strtoul(*arg++, 0, 16) : 0; - double const passband_end = n? --n, atof(*arg++) : 0; - double const stopband_begin = n? --n, atof(*arg++) : 0; - double const phase_response = n? --n, atof(*arg++) : -1; - int const use_threads = n? --n, atoi(*arg++) : 1; - soxr_datatype_t const otype = ospec & 3; - - soxr_quality_spec_t q_spec = soxr_quality_spec(q_recipe, q_flags); - soxr_io_spec_t io_spec = soxr_io_spec(itype, otype); - soxr_runtime_spec_t const runtime_spec = soxr_runtime_spec(!use_threads); - - /* Allocate resampling input and output buffers in proportion to the input - * and output rates: */ - #define buf_total_len 15000 /* In samples per channel. */ - size_t const osize = soxr_datatype_size(otype) * chans; - size_t const isize = soxr_datatype_size(itype) * chans; - size_t const olen0= (size_t)(orate * buf_total_len / (irate + orate) + .5); - size_t const olen = min(max(olen0, 1), buf_total_len - 1); - size_t const ilen = buf_total_len - olen; - void * const obuf = malloc(osize * olen); - void * const ibuf = malloc(isize * ilen); - - input_context_t icontext; - size_t odone, clips = 0; - soxr_error_t error; - soxr_t soxr; - - /* Overrides (if given): */ - if (passband_end > 0) q_spec.passband_end = passband_end / 100; - if (stopband_begin > 0) q_spec.stopband_begin = stopband_begin / 100; - if (phase_response >=0) q_spec.phase_response = phase_response; - io_spec.flags = ospec & ~7u; - - /* Create a stream resampler: */ - soxr = soxr_create( - irate, orate, chans, /* Input rate, output rate, # of channels. */ - &error, /* To report any error during creation. */ - &io_spec, &q_spec, &runtime_spec); - - if (!error) { /* Register input_fn with the resampler: */ - icontext.ibuf = ibuf, icontext.isize = isize; - error = soxr_set_input_fn(soxr, (soxr_input_fn_t)input_fn, &icontext, ilen); - } - - if (!error) { /* If all is well, run the resampler: */ - engine = soxr_engine(soxr); - USE_STD_STDIO; - /* Resample in blocks: */ - do odone = soxr_output(soxr, obuf, olen); - while (fwrite(obuf, osize, odone, stdout)); /* Consume output. */ - - error = soxr_error(soxr); /* Check if any soxr error occurred. */ - clips = *soxr_num_clips(soxr); /* Can occur only with integer output. */ - } - /* Tidy up: */ - soxr_delete(soxr); - free(obuf), free(ibuf); - /* Diagnostics: */ - fprintf(stderr, "%-26s %s; %lu clips; I/O: %s (%s)\n", - arg0, soxr_strerror(error), (long unsigned)clips, - ferror(stdin) || ferror(stdout)? strerror(errno) : "no error", engine); - return !!error; -} diff --git a/C/src/soxr-0.1.3/examples/4-split-channels.c b/C/src/soxr-0.1.3/examples/4-split-channels.c deleted file mode 100644 index a9022ce0..00000000 --- a/C/src/soxr-0.1.3/examples/4-split-channels.c +++ /dev/null @@ -1,161 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-18 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -/* Example 4: variant of examples 2 & 3, demonstrating I/O with split channels. - * - * Note that, for convenience of the demonstration, split-channel data is - * made available by deinterleaving data sourced from and sent to - * interleaved file-streams; this adds a lot of code to the example that, - * for purposes of understanding how to use split-channels, may safely be - * ignored. In a real application, the channel-data might never be - * interleaved; for example, the split-channel data output from the - * resampler might be sent directly to digital-to-analogue converters. - * - * Note also (not shown in the examples) that split/interleaved channels may - * be used for input and output independently. - * - * Arguments are as example 3. - */ - -#include -#include "examples-common.h" - - - -#define DEINTERLEAVE(T) do { \ - unsigned i; \ - size_t j; \ - T * const * dest = (T * const *)dest0; \ - T const * src = src0; \ - if (ch == 1) memcpy(dest[0], src, n * sizeof(dest[0][0])); \ - else for (j = 0; j < n; ++j) for (i = 0; i < ch; ++i) dest[i][j] = *src++; \ - return; \ -} while (0) - -static void deinterleave(soxr_datatype_t data_type, - void * const * dest0, - void const * src0, - size_t n, unsigned ch) -{ - switch (data_type & 3) { - case SOXR_FLOAT32: DEINTERLEAVE(float); - case SOXR_FLOAT64: DEINTERLEAVE(double); - case SOXR_INT32 : DEINTERLEAVE(int32_t); - case SOXR_INT16 : DEINTERLEAVE(int16_t); - default: break; - } -} - -#define INTERLEAVE(T) do { \ - unsigned i; \ - size_t j; \ - T * dest = dest0; \ - T const * const * src = (T const * const *)src0; \ - if (ch == 1) memcpy(dest, src[0], n * sizeof(dest[0])); \ - else for (j = 0; j < n; ++j) for (i = 0; i < ch; ++i) *dest++ = src[i][j]; \ - return; \ -} while (0) - -static void interleave(soxr_datatype_t data_type, void * dest0, - void * const * src0, size_t n, unsigned ch) -{ - switch (data_type & 3) { - case SOXR_FLOAT32: INTERLEAVE(float); - case SOXR_FLOAT64: INTERLEAVE(double); - case SOXR_INT32 : INTERLEAVE(int32_t); - case SOXR_INT16 : INTERLEAVE(int16_t); - default: break; - } -} - -int main(int n, char const * arg[]) -{ - char const * const arg0 = n? --n, *arg++ : ""; - double const irate = n? --n, atof(*arg++) : 96000.; - double const orate = n? --n, atof(*arg++) : 44100.; - unsigned const chans = n? --n, (unsigned)atoi(*arg++) : 1; - soxr_datatype_t const itype = n? --n, (soxr_datatype_t)atoi(*arg++) : 0; - unsigned const ospec = n? --n, (soxr_datatype_t)atoi(*arg++) : 0; - unsigned long const q_recipe= n? --n, strtoul(*arg++, 0, 16) : SOXR_HQ; - unsigned long const q_flags = n? --n, strtoul(*arg++, 0, 16) : 0; - double const passband_end = n? --n, atof(*arg++) : 0; - double const stopband_begin = n? --n, atof(*arg++) : 0; - double const phase_response = n? --n, atof(*arg++) : -1; - int const use_threads = n? --n, atoi(*arg++) : 1; - soxr_datatype_t const otype = ospec & 3; - - soxr_quality_spec_t q_spec = soxr_quality_spec(q_recipe, q_flags); - soxr_io_spec_t io_spec=soxr_io_spec(itype|SOXR_SPLIT, otype|SOXR_SPLIT); - soxr_runtime_spec_t const runtime_spec = soxr_runtime_spec(!use_threads); - - /* Allocate resampling input and output buffers in proportion to the input - * and output rates: */ - #define buf_total_len 15000 /* In samples per channel. */ - size_t const osize = soxr_datatype_size(otype) * chans; - size_t const isize = soxr_datatype_size(itype) * chans; - size_t const olen = (size_t)(orate * buf_total_len / (irate + orate) + .5); - size_t const ilen = buf_total_len - olen; - - /* For split channels: */ - void * * const obuf_ptrs = malloc(sizeof(void *) * chans); - void * * ibuf_ptrs = malloc(sizeof(void *) * chans); - char * const obufs = malloc(osize * olen), * optr = obufs; - char * const ibufs = malloc(isize * ilen), * iptr = ibufs; - - /* For interleaved channels: */ - char * const obuf = malloc(osize * olen); - char * const ibuf = malloc(isize * ilen); - - size_t odone, written, need_input = 1, clips = 0; - soxr_error_t error; - soxr_t soxr; - unsigned i; - - /* Overrides (if given): */ - if (passband_end > 0) q_spec.passband_end = passband_end / 100; - if (stopband_begin > 0) q_spec.stopband_begin = stopband_begin / 100; - if (phase_response >=0) q_spec.phase_response = phase_response; - io_spec.flags = ospec & ~7u; - - soxr = soxr_create( - irate, orate, chans, &error, &io_spec, &q_spec, &runtime_spec); - - for (i = 0; i < chans; ++i) { - ibuf_ptrs[i] = iptr; - obuf_ptrs[i] = optr; - iptr += ilen * soxr_datatype_size(itype); - optr += olen * soxr_datatype_size(otype); - } - - if (!error) { - USE_STD_STDIO; - - do { - size_t ilen1 = 0; - - if (need_input) { - if (!(ilen1 = fread(ibuf, isize, ilen, stdin))) - free(ibuf_ptrs), ibuf_ptrs = 0; /* If none available, don't retry. */ - else deinterleave(itype, ibuf_ptrs, ibuf, ilen1, chans); - } - - error = soxr_process(soxr, ibuf_ptrs, ilen1, NULL, obuf_ptrs, olen, &odone); - interleave(otype, obuf, obuf_ptrs, odone, chans); /* Consume output... */ - written = fwrite(obuf, osize, odone, stdout); - - need_input = odone < olen && ibuf_ptrs; - - } while (!error && (need_input || written)); - - clips = *soxr_num_clips(soxr); /* Can occur only with integer output. */ - } - /* Tidy up: */ - soxr_delete(soxr); - free(obuf), free(ibuf), free(obufs), free(ibufs); - free(obuf_ptrs), free(ibuf_ptrs); - /* Diagnostics: */ - fprintf(stderr, "%-26s %s; %lu clips; I/O: %s\n", - arg0, soxr_strerror(error), (long unsigned)clips, - ferror(stdin) || ferror(stdout)? strerror(errno) : "no error"); - return !!error; -} diff --git a/C/src/soxr-0.1.3/examples/5-variable-rate.c b/C/src/soxr-0.1.3/examples/5-variable-rate.c deleted file mode 100644 index 1a1c63f5..00000000 --- a/C/src/soxr-0.1.3/examples/5-variable-rate.c +++ /dev/null @@ -1,93 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -/* Example 5: Variable-rate resampling. A test signal (held in a buffer) is - * resampled over a wide range of octaves. Resampled data is sent to stdout as - * raw, float32 samples. Choices of 2 test-signals and of 2 ways of varying - * the sample-rate are combined in a command-line option: - * - * Usage: ./5-variable-rate [0|1|2|3] - */ - -#include -#include "examples-common.h" - -#define OCTAVES 5 /* Resampling range. ± */ -#define OLEN 16 /* Output length in seconds. */ -#define FS 44100 /* Output sampling rate in Hz. */ - -/* For output pos in [0,1], returns an ioratio in the 2^±OCTAVES range: */ -static double ioratio(double pos, int fm) -{ - if (fm) /* fm: non-0 for a fast-changing ioratio, 0 for a slow sweep. */ - pos = .5 - cos(pos * 2 * M_PI) * .4 + sin(pos * OLEN * 20 * M_PI) * .05; - return pow(2, 2 * OCTAVES * pos - OCTAVES); -} - -int main(int argc, char *arg[]) -{ - int opt = argc <= 1? 2 : (atoi(arg[1]) & 3), saw = opt & 1, fm = opt & 2; - float ibuf[10 << OCTAVES], obuf[AL(ibuf)]; - int i, wl = 2 << OCTAVES; - size_t ilen = AL(ibuf), need_input = 1, written; - size_t odone, total_odone, total_olen = OLEN * FS; - size_t olen1 = fm? 10 : AL(obuf); /* Small block-len if fast-changing ratio */ - soxr_error_t error; - - /* When creating a var-rate resampler, q_spec must be set as follows: */ - soxr_quality_spec_t q_spec = soxr_quality_spec(SOXR_HQ, SOXR_VR); - - /* The ratio of the given input rate and output rates must equate to the - * maximum I/O ratio that will be used: */ - soxr_t soxr = soxr_create(1 << OCTAVES, 1, 1, &error, NULL, &q_spec, NULL); - - if (!error) { - USE_STD_STDIO; - - /* Generate input signal, sine or saw, with wave-length = wl: */ - for (i = 0; i < (int)ilen; ++i) - ibuf[i] = (float)(saw? (i%wl)/(wl-1.)-.5 : .9 * sin(2 * M_PI * i / wl)); - - /* Set the initial resampling ratio (N.B. 3rd parameter = 0): */ - soxr_set_io_ratio(soxr, ioratio(0, fm), 0); - - /* Resample in blocks of size olen1: */ - for (total_odone = 0; !error && total_odone < total_olen;) { - - /* The last block might be shorter: */ - size_t block_len = min(olen1, total_olen - total_odone); - - /* Determine the position in [0,1] of the end of the current block: */ - double pos = (double)(total_odone + block_len) / (double)total_olen; - - /* Calculate an ioratio for this position and instruct the resampler to - * move smoothly to the new value, over the course of outputting the next - * 'block_len' samples (or give 0 for an instant change instead): */ - soxr_set_io_ratio(soxr, ioratio(pos, fm), block_len); - - /* Output the block of samples, supplying input samples as needed: */ - do { - size_t len = need_input? ilen : 0; - error = soxr_process(soxr, ibuf, len, NULL, obuf, block_len, &odone); - written = fwrite(obuf, sizeof(float), odone, stdout); - - /* Update counters for the current block and for the total length: */ - block_len -= odone; - total_odone += odone; - - /* If soxr_process did not provide the complete block, we must call it - * again, supplying more input samples: */ - need_input = block_len != 0; - - } while (need_input && !error && written == odone); - - /* Now that the block for the current ioratio is complete, go back - * round the main `for' loop in order to process the next block. */ - } - soxr_delete(soxr); - } - /* Diagnostics: */ - fprintf(stderr, "%-26s %s; I/O: %s\n", arg[0], soxr_strerror(error), - ferror(stdin) || ferror(stdout)? strerror(errno) : "no error"); - return !!error; -} diff --git a/C/src/soxr-0.1.3/examples/CMakeLists.txt b/C/src/soxr-0.1.3/examples/CMakeLists.txt deleted file mode 100644 index c8c17c96..00000000 --- a/C/src/soxr-0.1.3/examples/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -# SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net -# Licence for this file: LGPL v2.1 See LICENCE for details. - -set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${PROJECT_C_FLAGS}") -set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${PROJECT_CXX_FLAGS}") -link_libraries (${PROJECT_NAME} ${LIBM_LIBRARIES}) - -if (${BUILD_EXAMPLES} OR ${BUILD_TESTS}) - set (SOURCES 3-options-input-fn) - if (${WITH_LSR_BINDINGS}) - set (LSR_SOURCES 1a-lsr) - endif () -endif () - -if (${BUILD_EXAMPLES}) - list (APPEND SOURCES 1-single-block 2-stream 4-split-channels) - if (${WITH_VR32}) - list (APPEND SOURCES 5-variable-rate) - endif () -endif () - -foreach (fe ${SOURCES} ${LSR_SOURCES}) - get_filename_component (f ${fe} NAME_WE) - add_executable (${f} ${fe}) - if (${f} STREQUAL "1a-lsr") - target_link_libraries (${f} soxr-lsr) - endif () -endforeach () - -if (${BUILD_TESTS} AND ${WITH_LSR_BINDINGS}) - add_test (lsr-bindings ${BIN}1a-lsr) -endif () - -file (GLOB INSTALL_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.[cCh]) -install (FILES ${INSTALL_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/README - DESTINATION ${DOC_INSTALL_DIR}/examples) diff --git a/C/src/soxr-0.1.3/examples/README b/C/src/soxr-0.1.3/examples/README deleted file mode 100644 index a58939be..00000000 --- a/C/src/soxr-0.1.3/examples/README +++ /dev/null @@ -1,20 +0,0 @@ -SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net - -These simple examples show the different ways that an application may -interface with soxr. Note that real-world applications may also have to -deal with file-formats, codecs, (more sophisticated) dithering, etc., which -are not covered here. - -With the library installed, the examples may be built using commands similar -to the following. On unix-like systems: - - cc 1-single-block.c -lsoxr - cc 1a-lsr.c -lsoxr-lsr - -or, with MSVC on MS-Windows: - - cl 1-single-block.c -I"C:/Program Files/soxr/include" "C:/Program Files/soxr/lib/soxr.lib" - cl 1a-lsr.c -I"C:/Program Files/soxr/include" "C:/Program Files/soxr/lib/soxr-lsr.lib" - -IDEs may hide such commands behind configuration screens and build menus -- -where applicable, consult your IDE's user-manual. diff --git a/C/src/soxr-0.1.3/examples/examples-common.h b/C/src/soxr-0.1.3/examples/examples-common.h deleted file mode 100644 index fc8ed82e..00000000 --- a/C/src/soxr-0.1.3/examples/examples-common.h +++ /dev/null @@ -1,47 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-18 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -/* Common includes etc. for the examples. */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef _WIN32 - /* Work-around for broken file-I/O on MS-Windows: */ - #include - #include - #define USE_STD_STDIO _setmode(_fileno(stdout), _O_BINARY), \ - _setmode(_fileno(stdin ), _O_BINARY) -#else - #define USE_STD_STDIO -#endif - -#undef int16_t -#define int16_t short - -#undef int32_t -#if LONG_MAX > 2147483647L - #define int32_t int -#elif LONG_MAX < 2147483647L - #error this programme requires that 'long int' has at least 32-bits -#else - #define int32_t long -#endif - -#undef min -#define min(x,y) ((x)<(y)?(x):(y)) - -#undef max -#define max(x,y) ((x)>(y)?(x):(y)) - -#undef AL -#define AL(a) (sizeof(a)/sizeof((a)[0])) /* Array Length */ - -#undef M_PI /* Sometimes missing, so ensure that it is defined: */ -#define M_PI 3.14159265358979323846 diff --git a/C/src/soxr-0.1.3/go b/C/src/soxr-0.1.3/go deleted file mode 100755 index 786ed46d..00000000 --- a/C/src/soxr-0.1.3/go +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh -set -e - -# SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net -# Licence for this file: LGPL v2.1 See LICENCE for details. - -case "$1" in -j*) j="$1"; shift;; esac # Support -jX for parallel build/test - -test x"$1" = x && build=Release || build="$1" - -rm -f CMakeCache.txt # Prevent interference from any in-tree build - -mkdir -p "$build" -cd "$build" - -cmake -DCMAKE_INSTALL_PREFIX=$(pwd)/../../.. \ - -DCMAKE_POLICY_VERSION_MINIMUM=3.5 \ - -Wno-dev -DCMAKE_BUILD_TYPE="$build" \ - -DBUILD_SHARED_LIBS=OFF -DWITH_OPENMP=OFF .. -make $j -ctest $j || echo "FAILURE details in $build/Testing/Temporary/LastTest.log" diff --git a/C/src/soxr-0.1.3/go.bat b/C/src/soxr-0.1.3/go.bat deleted file mode 100644 index aabff75e..00000000 --- a/C/src/soxr-0.1.3/go.bat +++ /dev/null @@ -1,27 +0,0 @@ -@echo off -rem SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net -rem Licence for this file: LGPL v2.1 See LICENCE for details. - -set build=%1 -if x%build% == x set build=Release - -rem Prevent interference from any in-tree build -del/f CMakeCache.txt - -mkdir %build% -cd %build% - -cmake -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=%build% -Wno-dev .. -if errorlevel 1 goto end - -nmake -if errorlevel 1 goto end - -nmake test -if errorlevel 1 goto error -goto end - -:error -echo FAILURE details in Testing\Temporary\LastTest.log - -:end diff --git a/C/src/soxr-0.1.3/inst-check b/C/src/soxr-0.1.3/inst-check deleted file mode 100755 index 8cf64b76..00000000 --- a/C/src/soxr-0.1.3/inst-check +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/sh -set -e -# SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net -# Licence for this file: LGPL v2.1 See LICENCE for details. - -# Sanity-check of library installed on unix-like system - -# This script checks the installation of the entire library (including lsr). -# -# Distros using three separate packages can do the following (in order): -# -# * Install soxr pkg (i.e. basically, just the shared object) -# * ./inst-check-soxr -# * Install soxr-lsr pkg (i.e. basically, just the shared object) -# * ./inst-check-soxr-lsr -# * Install the -dev pkg (i.e. examples, headers, & pkg-config) -# * ./inst-check PATH-OF-INSTALLED-EXAMPLES-DIR (e.g. /usr/share/doc/libsoxr/examples) - -# Where are the example source files: -src=$1 -test x$src = x && src=/usr/local/share/doc/libsoxr/examples - -dir="$(dirname $(readlink -f $0))" -$dir/inst-check-soxr $src -$dir/inst-check-soxr-lsr $src diff --git a/C/src/soxr-0.1.3/inst-check-soxr b/C/src/soxr-0.1.3/inst-check-soxr deleted file mode 100755 index 5f923b84..00000000 --- a/C/src/soxr-0.1.3/inst-check-soxr +++ /dev/null @@ -1,52 +0,0 @@ -#!/bin/sh -set -e -# SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net -# Licence for this file: LGPL v2.1 See LICENCE for details. - -# Sanity-check of sub-library installed on unix-like system - -arg="$1" # path to installed examples (if dev pkg installed); otherwise omitted -dir="$(dirname $(readlink -f $0))" - -# Find the examples: -src="$arg" -test x"$src" = x && src="$dir/examples" -cd $src - -# Somewhere to put the binaries: -tmp=`mktemp -d` - -build_examples() { - if [ x"$arg" = x ]; then - echo "Examples in `pwd`; using local headers:" # for when dev pkg not installed - libs=-l$1 - cflags=-I$dir/src - else - echo "Examples in `pwd`; using pkg-config:" - libs=$(pkg-config --libs $1) - cflags=$(pkg-config --cflags $1) - fi - for f in ?$2-*.[cC]; do - cc=cc; echo $f | grep -q C$ && cc=c++ - out=$tmp/`echo $f | sed "s/.[cC]$//"` - cmd="$cc $cflags -o $out $f $libs -lm" - echo $cmd; $cmd - done -} - -# Determine library: -if [ `basename $0` = inst-check-soxr ]; then - build_examples soxr - gen="dd if=/dev/urandom count=1000" - $tmp/1-single-block 1 2 . - $gen 2> /dev/null | $tmp/2-stream 2>&1 >$tmp/stdout - $gen 2> /dev/null | $tmp/3-options-input-fn 6 7 2 2 0 2>&1 >$tmp/stdout - $gen 2> /dev/null | $tmp/4-split-channels 7 6 2 2 3 2>&1 >$tmp/stdout # Clipping expected here - $gen 2> /dev/null | $tmp/5-variable-rate 2>&1 >$tmp/stdout -else - build_examples soxr-lsr a # lsr has 'a' suffix on example number. - $tmp/1a-lsr 1 2 . -fi - -# Tidy up: -rm -rf $tmp diff --git a/C/src/soxr-0.1.3/inst-check-soxr-lsr b/C/src/soxr-0.1.3/inst-check-soxr-lsr deleted file mode 120000 index ec971fb7..00000000 --- a/C/src/soxr-0.1.3/inst-check-soxr-lsr +++ /dev/null @@ -1 +0,0 @@ -inst-check-soxr \ No newline at end of file diff --git a/C/src/soxr-0.1.3/msvc/README b/C/src/soxr-0.1.3/msvc/README deleted file mode 100644 index 5b7f60a5..00000000 --- a/C/src/soxr-0.1.3/msvc/README +++ /dev/null @@ -1,22 +0,0 @@ -SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net - -Cmake is the recommended way to configure, build (as either a DLL or a static -library), and install libsoxr for general use on MS-Windows, as on other OSs. - -However, building within MS Visual Studio is also possible, as exemplified by -the accompanying files: - - * soxr-config.h Pre-configured for a modern Win32 system. - - * libsoxr.vcproj Builds the library as a DLL, per above. - - * libsoxr.sln, Build an example exe using the above. - example1.vcproj - -The following notes apply to adaptation of these files: - - * For a system without AVX support, set WITH_CR64S to 0 in - soxr-config.h and exclude the three files ...64s.c from the build. - - * If changing libsoxr.vcproj to build a static library, then also - remove the preprocessor definition: SOXR_DLL. diff --git a/C/src/soxr-0.1.3/msvc/example1.vcproj b/C/src/soxr-0.1.3/msvc/example1.vcproj deleted file mode 100644 index 1523855c..00000000 --- a/C/src/soxr-0.1.3/msvc/example1.vcproj +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/C/src/soxr-0.1.3/msvc/libsoxr.sln b/C/src/soxr-0.1.3/msvc/libsoxr.sln deleted file mode 100644 index bb3e9c74..00000000 --- a/C/src/soxr-0.1.3/msvc/libsoxr.sln +++ /dev/null @@ -1,29 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual C++ Express 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example1", "example1.vcproj", "{CA28595B-B14F-45FD-BA56-FBDFFB70FFC4}" - ProjectSection(ProjectDependencies) = postProject - {4916B0C1-2F99-433A-B88A-A99CB4E1E0AB} = {4916B0C1-2F99-433A-B88A-A99CB4E1E0AB} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libsoxr", "libsoxr.vcproj", "{4916B0C1-2F99-433A-B88A-A99CB4E1E0AB}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Release|Win32 = Release|Win32 - Debug|Win32 = Debug|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {CA28595B-B14F-45FD-BA56-FBDFFB70FFC4}.Release|Win32.ActiveCfg = Release|Win32 - {CA28595B-B14F-45FD-BA56-FBDFFB70FFC4}.Release|Win32.Build.0 = Release|Win32 - {CA28595B-B14F-45FD-BA56-FBDFFB70FFC4}.Debug|Win32.ActiveCfg = Debug|Win32 - {CA28595B-B14F-45FD-BA56-FBDFFB70FFC4}.Debug|Win32.Build.0 = Debug|Win32 - {4916B0C1-2F99-433A-B88A-A99CB4E1E0AB}.Release|Win32.ActiveCfg = Release|Win32 - {4916B0C1-2F99-433A-B88A-A99CB4E1E0AB}.Release|Win32.Build.0 = Release|Win32 - {4916B0C1-2F99-433A-B88A-A99CB4E1E0AB}.Debug|Win32.ActiveCfg = Debug|Win32 - {4916B0C1-2F99-433A-B88A-A99CB4E1E0AB}.Debug|Win32.Build.0 = Debug|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/C/src/soxr-0.1.3/msvc/libsoxr.vcproj b/C/src/soxr-0.1.3/msvc/libsoxr.vcproj deleted file mode 100644 index 65ee42dc..00000000 --- a/C/src/soxr-0.1.3/msvc/libsoxr.vcproj +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/C/src/soxr-0.1.3/msvc/soxr-config.h b/C/src/soxr-0.1.3/msvc/soxr-config.h deleted file mode 100644 index 89f7a91f..00000000 --- a/C/src/soxr-0.1.3/msvc/soxr-config.h +++ /dev/null @@ -1,30 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -/* N.B. Pre-configured for modern MS-Windows systems. However, the normal - * procedure is to use the cmake configuration and build system. See INSTALL. */ - -#if !defined soxr_config_included -#define soxr_config_included - -#define AVCODEC_FOUND 0 -#define AVUTIL_FOUND 0 -#define WITH_PFFFT 1 - -#define HAVE_FENV_H 1 -#define HAVE_STDBOOL_H 1 -#define HAVE_STDINT_H 1 -#define HAVE_LRINT 1 -#define HAVE_BIGENDIAN 0 - -#define WITH_CR32 1 -#define WITH_CR32S 1 -#define WITH_CR64 1 -#define WITH_CR64S 1 -#define WITH_VR32 1 - -#define WITH_HI_PREC_CLOCK 1 -#define WITH_FLOAT_STD_PREC_CLOCK 0 -#define WITH_DEV_TRACE 1 - -#endif diff --git a/C/src/soxr-0.1.3/multi-arch b/C/src/soxr-0.1.3/multi-arch deleted file mode 100755 index 288b5780..00000000 --- a/C/src/soxr-0.1.3/multi-arch +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env bash -set -e - -# SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net -# Licence for this file: LGPL v2.1 See LICENCE for details. - -rm -f CMakeCache.txt # Prevent interference from any in-tree build - -j=-j4 -build=Release - -for n in \ - cc: \ - clang: \ - arm-linux-gnueabi-gcc:Linux \ - x86_64-w64-mingw32-gcc:Windows \ - i686-w64-mingw32-gcc:Windows \ - ; do - compiler=$(echo $n | sed 's/:.*//') - system=$(echo $n | sed 's/.*://') - dir=$build-$compiler - which $compiler > /dev/null || echo $compiler not found && ( - echo "***" $dir - mkdir -p $dir - cd $dir - cmake -DCMAKE_BUILD_TYPE=$build -DCMAKE_C_COMPILER=$compiler -DCMAKE_SYSTEM_NAME="$system" -DBUILD_SHARED_LIBS=OFF -DWITH_OPENMP=OFF .. - make $j && [ /$system = / ] && ctest -j || true - cd tests - ../../tests/throughput-test && SOXR_THROUGHPUT_GAIN=.6 ../../tests/throughput-test 2 3 || true - ) -done diff --git a/C/src/soxr-0.1.3/soxr-config.h.in b/C/src/soxr-0.1.3/soxr-config.h.in deleted file mode 100644 index 00b3b457..00000000 --- a/C/src/soxr-0.1.3/soxr-config.h.in +++ /dev/null @@ -1,27 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#if !defined soxr_config_included -#define soxr_config_included - -#cmakedefine01 AVCODEC_FOUND -#cmakedefine01 AVUTIL_FOUND -#cmakedefine01 WITH_PFFFT - -#cmakedefine01 HAVE_FENV_H -#cmakedefine01 HAVE_STDBOOL_H -#cmakedefine01 HAVE_STDINT_H -#cmakedefine01 HAVE_LRINT -#cmakedefine01 HAVE_BIGENDIAN - -#cmakedefine01 WITH_CR32 -#cmakedefine01 WITH_CR32S -#cmakedefine01 WITH_CR64 -#cmakedefine01 WITH_CR64S -#cmakedefine01 WITH_VR32 - -#cmakedefine01 WITH_HI_PREC_CLOCK -#cmakedefine01 WITH_FLOAT_STD_PREC_CLOCK -#cmakedefine01 WITH_DEV_TRACE - -#endif diff --git a/C/src/soxr-0.1.3/src/CMakeLists.txt b/C/src/soxr-0.1.3/src/CMakeLists.txt deleted file mode 100644 index bb01a0d7..00000000 --- a/C/src/soxr-0.1.3/src/CMakeLists.txt +++ /dev/null @@ -1,129 +0,0 @@ -# SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net -# Licence for this file: LGPL v2.1 See LICENCE for details. - - - -# Can generate vr-coefs.h but it complicates cross-compiling & non-cmake builds - -if (NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/vr-coefs.h) - include_directories(${CMAKE_CURRENT_BINARY_DIR}) - set_property(SOURCE vr32.c - APPEND PROPERTY OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/vr-coefs.h) - add_executable (vr-coefs vr-coefs.c) - target_link_libraries (vr-coefs ${LIBM_LIBRARIES}) - ADD_CUSTOM_COMMAND(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/vr-coefs.h - COMMAND vr-coefs > ${CMAKE_CURRENT_BINARY_DIR}/vr-coefs.h - DEPENDS vr-coefs) -endif () - - - -add_definitions (${PROJECT_C_FLAGS} -DSOXR_LIB) - - - -# Libsoxr configuration: - -set (RDFT32 fft4g32) -if (AVCODEC_FOUND) - set (RDFT32 avfft32) - set (RDFT32S avfft32s) -elseif (WITH_PFFFT) - #set (RDFT32 pffft32) - set (RDFT32S pffft32s) -elseif (WITH_CR32S) - set (RDFT32S fft4g32s) - if (NOT WITH_CR32) - list (APPEND RDFT32S fft4g32) - endif () -endif () - -set (SOURCES ${PROJECT_NAME}.c data-io) - -if (WITH_CR32 OR WITH_CR32S OR WITH_CR64 OR WITH_CR64S) - list (APPEND SOURCES dbesi0 filter fft4g64 cr) -endif () - -if (WITH_CR32) - list (APPEND SOURCES cr32 ${RDFT32}) -endif () - -if (WITH_CR64) - list (APPEND SOURCES cr64) -endif () - -if (WITH_VR32) - list (APPEND SOURCES vr32) -endif () - -if (WITH_CR32S) - foreach (source cr32s ${RDFT32S} util32s) - list (APPEND SOURCES ${source}) - set_property (SOURCE ${source} - APPEND_STRING PROPERTY COMPILE_FLAGS ${SIMD32_C_FLAGS}) - endforeach () -endif () - -if (WITH_CR64S) - foreach (source cr64s pffft64s util64s) - list (APPEND SOURCES ${source}) - set_property (SOURCE ${source} - APPEND_STRING PROPERTY COMPILE_FLAGS ${SIMD64_C_FLAGS}) - endforeach () -endif () - - - -# Libsoxr: - -add_library (${PROJECT_NAME} ${LIB_TYPE} ${SOURCES}) -target_link_libraries (${PROJECT_NAME} PRIVATE ${LIBS} ${LIBM_LIBRARIES}) -set_target_properties (${PROJECT_NAME} PROPERTIES - VERSION "${SO_VERSION}" - SOVERSION ${SO_VERSION_MAJOR} - INSTALL_NAME_DIR ${LIB_INSTALL_DIR} - LINK_INTERFACE_LIBRARIES "" - PUBLIC_HEADER "${PROJECT_NAME}.h") -if (BUILD_FRAMEWORK) - set_target_properties (${PROJECT_NAME} PROPERTIES FRAMEWORK TRUE) -elseif (NOT WIN32) - set (TARGET_PCS ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc) - configure_file (${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.pc.in ${TARGET_PCS}) - install (FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) -endif () - - - -# LSR bindings: - -if (WITH_LSR_BINDINGS) - set (LSR ${PROJECT_NAME}-lsr) - set (LSR_SO_VERSION 0.1.9) - set (LSR_SO_VERSION_MAJOR 0) - add_library (${LSR} ${LIB_TYPE} ${LSR}) - target_link_libraries (${LSR} ${PROJECT_NAME}) - set_target_properties (${LSR} PROPERTIES - VERSION "${LSR_SO_VERSION}" - SOVERSION ${LSR_SO_VERSION_MAJOR} - INSTALL_NAME_DIR ${LIB_INSTALL_DIR} - LINK_INTERFACE_LIBRARIES "" - PUBLIC_HEADER "${LSR}.h") - if (BUILD_FRAMEWORK) - set_target_properties (${LSR} PROPERTIES FRAMEWORK TRUE) - elseif (NOT WIN32) - set (TARGET_PCS "${TARGET_PCS} ${CMAKE_CURRENT_BINARY_DIR}/${LSR}.pc") - configure_file (${CMAKE_CURRENT_SOURCE_DIR}/${LSR}.pc.in ${CMAKE_CURRENT_BINARY_DIR}/${LSR}.pc) - install (FILES ${CMAKE_CURRENT_BINARY_DIR}/${LSR}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) - endif () -endif () - - - -# Installation (from build from source): - -install (TARGETS ${PROJECT_NAME} ${LSR} - FRAMEWORK DESTINATION ${FRAMEWORK_INSTALL_DIR} - LIBRARY DESTINATION ${LIB_INSTALL_DIR} - RUNTIME DESTINATION ${BIN_INSTALL_DIR} - ARCHIVE DESTINATION ${LIB_INSTALL_DIR} - PUBLIC_HEADER DESTINATION ${INCLUDE_INSTALL_DIR}) diff --git a/C/src/soxr-0.1.3/src/aliases.h b/C/src/soxr-0.1.3/src/aliases.h deleted file mode 100644 index d1a392f6..00000000 --- a/C/src/soxr-0.1.3/src/aliases.h +++ /dev/null @@ -1,39 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#if defined SOXR_LIB - -#define lsx_bessel_I_0 _soxr_bessel_I_0 -#define lsx_cdft_f _soxr_cdft_f -#define lsx_cdft _soxr_cdft -#define lsx_clear_fft_cache_f _soxr_clear_fft_cache_f -#define lsx_clear_fft_cache _soxr_clear_fft_cache -#define lsx_ddct_f _soxr_ddct_f -#define lsx_ddct _soxr_ddct -#define lsx_ddst_f _soxr_ddst_f -#define lsx_ddst _soxr_ddst -#define lsx_design_lpf _soxr_design_lpf -#define lsx_dfct_f _soxr_dfct_f -#define lsx_dfct _soxr_dfct -#define lsx_dfst_f _soxr_dfst_f -#define lsx_dfst _soxr_dfst -#define lsx_fir_to_phase _soxr_fir_to_phase -#define lsx_f_resp _soxr_f_resp -#define lsx_init_fft_cache_f _soxr_init_fft_cache_f -#define lsx_init_fft_cache _soxr_init_fft_cache -#define lsx_inv_f_resp _soxr_inv_f_resp -#define lsx_kaiser_beta _soxr_kaiser_beta -#define lsx_kaiser_params _soxr_kaiser_params -#define lsx_make_lpf _soxr_make_lpf -#define lsx_ordered_convolve_f _soxr_ordered_convolve_f -#define lsx_ordered_convolve _soxr_ordered_convolve -#define lsx_ordered_partial_convolve_f _soxr_ordered_partial_convolve_f -#define lsx_ordered_partial_convolve _soxr_ordered_partial_convolve -#define lsx_rdft_f _soxr_rdft_f -#define lsx_rdft _soxr_rdft -#define lsx_safe_cdft_f _soxr_safe_cdft_f -#define lsx_safe_cdft _soxr_safe_cdft -#define lsx_safe_rdft_f _soxr_safe_rdft_f -#define lsx_safe_rdft _soxr_safe_rdft - -#endif diff --git a/C/src/soxr-0.1.3/src/avfft32.c b/C/src/soxr-0.1.3/src/avfft32.c deleted file mode 100644 index fe651f5d..00000000 --- a/C/src/soxr-0.1.3/src/avfft32.c +++ /dev/null @@ -1,33 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#include -#include -#include -#include "filter.h" -#include "rdft_t.h" - -static void * forward_setup(int len) {return av_rdft_init((int)(log(len)/log(2)+.5),DFT_R2C);} -static void * backward_setup(int len) {return av_rdft_init((int)(log(len)/log(2)+.5),IDFT_C2R);} -static void rdft(int length, void * setup, float * h) {av_rdft_calc(setup, h); (void)length;} -static int multiplier(void) {return 2;} -static void nothing(void) {} -static int flags(void) {return 0;} - -fn_t _soxr_rdft32_cb[] = { - (fn_t)forward_setup, - (fn_t)backward_setup, - (fn_t)av_rdft_end, - (fn_t)rdft, - (fn_t)rdft, - (fn_t)rdft, - (fn_t)rdft, - (fn_t)_soxr_ordered_convolve_f, - (fn_t)_soxr_ordered_partial_convolve_f, - (fn_t)multiplier, - (fn_t)nothing, - (fn_t)malloc, - (fn_t)calloc, - (fn_t)free, - (fn_t)flags, -}; diff --git a/C/src/soxr-0.1.3/src/avfft32s.c b/C/src/soxr-0.1.3/src/avfft32s.c deleted file mode 100644 index 5a7e62db..00000000 --- a/C/src/soxr-0.1.3/src/avfft32s.c +++ /dev/null @@ -1,32 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#include -#include -#include "util32s.h" -#include "rdft_t.h" - -static void * forward_setup(int len) {return av_rdft_init((int)(log(len)/log(2)+.5),DFT_R2C);} -static void * backward_setup(int len) {return av_rdft_init((int)(log(len)/log(2)+.5),IDFT_C2R);} -static void rdft(int length, void * setup, float * h) {av_rdft_calc(setup, h); (void)length;} -static int multiplier(void) {return 2;} -static void nothing(void) {} -static int flags(void) {return RDFT_IS_SIMD;} - -fn_t _soxr_rdft32s_cb[] = { - (fn_t)forward_setup, - (fn_t)backward_setup, - (fn_t)av_rdft_end, - (fn_t)rdft, - (fn_t)rdft, - (fn_t)rdft, - (fn_t)rdft, - (fn_t)ORDERED_CONVOLVE_SIMD, - (fn_t)ORDERED_PARTIAL_CONVOLVE_SIMD, - (fn_t)multiplier, - (fn_t)nothing, - (fn_t)SIMD_ALIGNED_MALLOC, - (fn_t)SIMD_ALIGNED_CALLOC, - (fn_t)SIMD_ALIGNED_FREE, - (fn_t)flags, -}; diff --git a/C/src/soxr-0.1.3/src/ccrw2.h b/C/src/soxr-0.1.3/src/ccrw2.h deleted file mode 100644 index 09331a4b..00000000 --- a/C/src/soxr-0.1.3/src/ccrw2.h +++ /dev/null @@ -1,75 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -/* Concurrent Control with "Readers" and "Writers", P.J. Courtois et al, 1971 */ - -#if !defined soxr_ccrw2_included -#define soxr_ccrw2_included - -#if defined SOXR_LIB -#include "internal.h" -#endif - -#if defined _OPENMP - -#include - -typedef struct { - int readcount, writecount; /* initial value = 0 */ - omp_lock_t mutex_1, mutex_2, mutex_3, w, r; /* initial value = 1 */ -} ccrw2_t; /* Problem #2: `writers-preference' */ - -#define ccrw2_become_reader(p) do {\ - omp_set_lock(&p.mutex_3);\ - omp_set_lock(&p.r);\ - omp_set_lock(&p.mutex_1);\ - if (++p.readcount == 1) omp_set_lock(&p.w);\ - omp_unset_lock(&p.mutex_1);\ - omp_unset_lock(&p.r);\ - omp_unset_lock(&p.mutex_3);\ -} while (0) -#define ccrw2_cease_reading(p) do {\ - omp_set_lock(&p.mutex_1);\ - if (!--p.readcount) omp_unset_lock(&p.w);\ - omp_unset_lock(&p.mutex_1);\ -} while (0) -#define ccrw2_become_writer(p) do {\ - omp_set_lock(&p.mutex_2);\ - if (++p.writecount == 1) omp_set_lock(&p.r);\ - omp_unset_lock(&p.mutex_2);\ - omp_set_lock(&p.w);\ -} while (0) -#define ccrw2_cease_writing(p) do {\ - omp_unset_lock(&p.w);\ - omp_set_lock(&p.mutex_2);\ - if (!--p.writecount) omp_unset_lock(&p.r);\ - omp_unset_lock(&p.mutex_2);\ -} while (0) -#define ccrw2_init(p) do {\ - omp_init_lock(&p.mutex_1);\ - omp_init_lock(&p.mutex_2);\ - omp_init_lock(&p.mutex_3);\ - omp_init_lock(&p.w);\ - omp_init_lock(&p.r);\ -} while (0) -#define ccrw2_clear(p) do {\ - omp_destroy_lock(&p.r);\ - omp_destroy_lock(&p.w);\ - omp_destroy_lock(&p.mutex_3);\ - omp_destroy_lock(&p.mutex_2);\ - omp_destroy_lock(&p.mutex_1);\ -} while (0) - -#else - -typedef int ccrw2_t; -#define ccrw2_become_reader(x) (void)(x) -#define ccrw2_cease_reading(x) (void)(x) -#define ccrw2_become_writer(x) (void)(x) -#define ccrw2_cease_writing(x) (void)(x) -#define ccrw2_init(x) (void)(x) -#define ccrw2_clear(x) (void)(x) - -#endif /* _OPENMP */ - -#endif diff --git a/C/src/soxr-0.1.3/src/cr-core.c b/C/src/soxr-0.1.3/src/cr-core.c deleted file mode 100644 index 159a5d97..00000000 --- a/C/src/soxr-0.1.3/src/cr-core.c +++ /dev/null @@ -1,314 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-18 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. - * - * Constant-rate resampling engine-specific code. */ - -#include -#include -#include -#include - -#include "filter.h" - -#if defined SOXR_LIB - #include "internal.h" - #include "cr.h" - #if CORE_TYPE & CORE_DBL - typedef double sample_t; - #if CORE_TYPE & CORE_SIMD_DFT - #define RDFT_CB _soxr_rdft64s_cb - #else - #define RDFT_CB _soxr_rdft64_cb - #endif - #else - typedef float sample_t; - #if CORE_TYPE & CORE_SIMD_DFT - #define RDFT_CB _soxr_rdft32s_cb - #else - #define RDFT_CB _soxr_rdft32_cb - #endif - #endif - - #if CORE_TYPE & (CORE_SIMD_POLY|CORE_SIMD_HALF|CORE_SIMD_DFT) - #if CORE_TYPE & CORE_DBL - #include "util64s.h" - #include "dev64s.h" - #else - #include "util32s.h" - #include "dev32s.h" - #endif - #endif - - extern fn_t RDFT_CB[]; -#else - #define RDFT_CB 0 -#endif - - - -static void cubic_stage_fn(stage_t * p, fifo_t * output_fifo) -{ - sample_t const * input = stage_read_p(p); - int num_in = min(stage_occupancy(p), p->input_size); - int i, max_num_out = 1 + (int)(num_in * p->out_in_ratio); - sample_t * output = fifo_reserve(output_fifo, max_num_out); - - for (i = 0; p->at.integer < num_in; ++i, p->at.whole += p->step.whole) { - sample_t const * s = input + p->at.integer; - double x = p->at.fraction * (1 / MULT32); - double b = .5*(s[1]+s[-1])-*s, a = (1/6.)*(s[2]-s[1]+s[-1]-*s-4*b); - double c = s[1]-*s-a-b; - output[i] = (sample_t)(p->mult * (((a*x + b)*x + c)*x + *s)); - } - assert(max_num_out - i >= 0); - fifo_trim_by(output_fifo, max_num_out - i); - fifo_read(&p->fifo, p->at.integer, NULL); - p->at.integer = 0; -} - - - -#if defined __AVX__ - #define DEFINED_AVX 1 -#else - #define DEFINED_AVX 0 -#endif - -#if defined __x86_64__ || defined _M_X64 || defined i386 || defined _M_IX86 - #define DEFINED_X86 1 -#else - #define DEFINED_X86 0 -#endif - -#if defined __arm__ - #define DEFINED_ARM 1 -#else - #define DEFINED_ARM 0 -#endif - - - -#if CORE_TYPE & CORE_DBL - #define SIMD_AVX ((CORE_TYPE & CORE_SIMD_HALF) && DEFINED_AVX) - #define SIMD_SSE 0 -#else - #define SIMD_SSE ((CORE_TYPE & CORE_SIMD_HALF) && DEFINED_X86) - #define SIMD_AVX 0 -#endif - -#define SIMD_NEON ((CORE_TYPE & CORE_SIMD_HALF) && DEFINED_ARM) - - - -#include "half-coefs.h" - -#if !(CORE_TYPE & CORE_SIMD_HALF) -#define FUNCTION_H h7 -#define CONVOLVE ____ __ _ -#include "half-fir.h" -#endif - -#define FUNCTION_H h8 -#define CONVOLVE ____ ____ -#include "half-fir.h" - -#define FUNCTION_H h9 -#define CONVOLVE ____ ____ _ -#include "half-fir.h" - -#if CORE_TYPE & CORE_DBL - #define FUNCTION_H h10 - #define CONVOLVE ____ ____ __ - #include "half-fir.h" - - #define FUNCTION_H h11 - #define CONVOLVE ____ ____ __ _ - #include "half-fir.h" - - #define FUNCTION_H h12 - #define CONVOLVE ____ ____ ____ - #include "half-fir.h" - - #define FUNCTION_H h13 - #define CONVOLVE ____ ____ ____ _ - #include "half-fir.h" -#endif - -static half_fir_info_t const half_firs[] = { -#if !(CORE_TYPE & CORE_SIMD_HALF) - { 7, half_fir_coefs_7 , h7 , 0 , 120.65f}, -#endif - { 8, half_fir_coefs_8 , h8 , 0 , 136.51f}, - { 9, half_fir_coefs_9 , h9 , 0 , 152.32f}, -#if CORE_TYPE & CORE_DBL - {10, half_fir_coefs_10, h10, 0 , 168.08f}, - {11, half_fir_coefs_11, h11, 0 , 183.79f}, - {12, half_fir_coefs_12, h12, 0 , 199.46f}, - {13, half_fir_coefs_13, h13, 0 , 215.12f}, -#endif -}; - -#undef SIMD_AVX -#undef SIMD_NEON -#undef SIMD_SSE - - - -#if CORE_TYPE & CORE_DBL - #define SIMD_AVX ((CORE_TYPE & CORE_SIMD_POLY) && DEFINED_AVX) - #define SIMD_SSE 0 -#else - #define SIMD_SSE ((CORE_TYPE & CORE_SIMD_POLY) && DEFINED_X86) - #define SIMD_AVX 0 -#endif - -#define SIMD_NEON ((CORE_TYPE & CORE_SIMD_POLY) && DEFINED_ARM) - - - -#define COEFS (sample_t * __restrict)p->shared->poly_fir_coefs -#define VAR_LENGTH p->n -#define VAR_CONVOLVE(n) while (j < (n)) _ -#define VAR_POLY_PHASE_BITS p->phase_bits - - - -#define FUNCTION vpoly0 -#define FIR_LENGTH VAR_LENGTH -#define CONVOLVE(n) VAR_CONVOLVE(n) -#include "poly-fir0.h" - -#define FUNCTION vpoly1 -#define COEF_INTERP 1 -#define PHASE_BITS VAR_POLY_PHASE_BITS -#define FIR_LENGTH VAR_LENGTH -#define CONVOLVE(n) VAR_CONVOLVE(n) -#include "poly-fir.h" - -#define FUNCTION vpoly2 -#define COEF_INTERP 2 -#define PHASE_BITS VAR_POLY_PHASE_BITS -#define FIR_LENGTH VAR_LENGTH -#define CONVOLVE(n) VAR_CONVOLVE(n) -#include "poly-fir.h" - -#define FUNCTION vpoly3 -#define COEF_INTERP 3 -#define PHASE_BITS VAR_POLY_PHASE_BITS -#define FIR_LENGTH VAR_LENGTH -#define CONVOLVE(n) VAR_CONVOLVE(n) -#include "poly-fir.h" - - - -#if !(CORE_TYPE & CORE_SIMD_POLY) - -#define poly_fir_convolve_U100 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ -#define FUNCTION U100_0 -#define FIR_LENGTH U100_l -#define CONVOLVE(n) poly_fir_convolve_U100 -#include "poly-fir0.h" - -#define u100_l 11 -#define poly_fir_convolve_u100 _ _ _ _ _ _ _ _ _ _ _ -#define FUNCTION u100_0 -#define FIR_LENGTH u100_l -#define CONVOLVE(n) poly_fir_convolve_u100 -#include "poly-fir0.h" - -#define FUNCTION u100_1 -#define COEF_INTERP 1 -#define PHASE_BITS 8 -#define FIR_LENGTH u100_l -#define CONVOLVE(n) poly_fir_convolve_u100 -#include "poly-fir.h" - -#define FUNCTION u100_2 -#define COEF_INTERP 2 -#define PHASE_BITS 6 -#define FIR_LENGTH u100_l -#define CONVOLVE(n) poly_fir_convolve_u100 -#include "poly-fir.h" - -#endif - -#define u100_1_b 8 -#define u100_2_b 6 - - - -static poly_fir_t const poly_firs[] = { - {-1, {{0, vpoly0}, { 7.2f, vpoly1}, {5.0f, vpoly2}}}, - {-1, {{0, vpoly0}, { 9.4f, vpoly1}, {6.7f, vpoly2}}}, - {-1, {{0, vpoly0}, {12.4f, vpoly1}, {7.8f, vpoly2}}}, - {-1, {{0, vpoly0}, {13.6f, vpoly1}, {9.3f, vpoly2}}}, - {-1, {{0, vpoly0}, {10.5f, vpoly2}, {8.4f, vpoly3}}}, - {-1, {{0, vpoly0}, {11.85f,vpoly2}, {9.0f, vpoly3}}}, - - {-1, {{0, vpoly0}, { 8.0f, vpoly1}, {5.3f, vpoly2}}}, - {-1, {{0, vpoly0}, { 8.6f, vpoly1}, {5.7f, vpoly2}}}, - {-1, {{0, vpoly0}, {10.6f, vpoly1}, {6.75f,vpoly2}}}, - {-1, {{0, vpoly0}, {12.6f, vpoly1}, {8.6f, vpoly2}}}, - {-1, {{0, vpoly0}, { 9.6f, vpoly2}, {7.6f, vpoly3}}}, - {-1, {{0, vpoly0}, {11.4f, vpoly2}, {8.65f,vpoly3}}}, - -#if CORE_TYPE & CORE_SIMD_POLY - {10.62f, {{0, vpoly0}, {0, 0}, {0, 0}}}, - {-1, {{0, vpoly0}, {u100_1_b, vpoly1}, {u100_2_b, vpoly2}}}, -#else - {10.62f, {{U100_l, U100_0}, {0, 0}, {0, 0}}}, - {11.28f, {{u100_l, u100_0}, {u100_1_b, u100_1}, {u100_2_b, u100_2}}}, -#endif - {-1, {{0, vpoly0}, { 9, vpoly1}, { 6, vpoly2}}}, - {-1, {{0, vpoly0}, { 11, vpoly1}, { 7, vpoly2}}}, - {-1, {{0, vpoly0}, { 13, vpoly1}, { 8, vpoly2}}}, - {-1, {{0, vpoly0}, { 10, vpoly2}, { 8, vpoly3}}}, - {-1, {{0, vpoly0}, { 12, vpoly2}, { 9, vpoly3}}}, -}; - - - -static cr_core_t const cr_core = { - -#if CORE_TYPE & CORE_SIMD_POLY - {SIMD_ALIGNED_MALLOC, SIMD_ALIGNED_CALLOC, SIMD_ALIGNED_FREE}, -#else - {malloc, calloc, free}, -#endif - half_firs, array_length(half_firs), - 0, 0, - cubic_stage_fn, - poly_firs, RDFT_CB -}; - - - -#if defined SOXR_LIB - -#include "soxr.h" - -static char const * rate_create(void * channel, void * shared, double io_ratio, - soxr_quality_spec_t * q_spec, soxr_runtime_spec_t * r_spec, double scale) -{ - return _soxr_init(channel, shared, io_ratio, q_spec, r_spec, scale, - &cr_core, CORE_TYPE); -} - - - -static char const * id(void) {return CORE_STR;} - -fn_t RATE_CB[] = { - (fn_t)_soxr_input, - (fn_t)_soxr_process, - (fn_t)_soxr_output, - (fn_t)_soxr_flush, - (fn_t)_soxr_close, - (fn_t)_soxr_delay, - (fn_t)_soxr_sizes, - (fn_t)rate_create, - (fn_t)0, - (fn_t)id, -}; - -#endif diff --git a/C/src/soxr-0.1.3/src/cr.c b/C/src/soxr-0.1.3/src/cr.c deleted file mode 100644 index 4122db3c..00000000 --- a/C/src/soxr-0.1.3/src/cr.c +++ /dev/null @@ -1,588 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. - * - * Constant-rate resampling common code. */ - -#include -#include -#include -#include - -#include "filter.h" - -#if defined SOXR_LIB - #include "internal.h" - #define STATIC -#endif - -#include "cr.h" - -#define num_coefs4 ((core_flags&CORE_SIMD_POLY)? ((num_coefs+3)&~3) : num_coefs) - -#define coef_coef(C,T,x) \ - C((T*)result, interp_order, num_coefs4, j, x, num_coefs4 - 1 - i) - -#define STORE(C,T) { \ - if (interp_order > 2) coef_coef(C,T,3) = (T)d; \ - if (interp_order > 1) coef_coef(C,T,2) = (T)c; \ - if (interp_order > 0) coef_coef(C,T,1) = (T)b; \ - coef_coef(C,T,0) = (T)f0;} - -static real * prepare_poly_fir_coefs(double const * coefs, int num_coefs, - int num_phases, int interp_order, double multiplier, - core_flags_t core_flags, alloc_t const * mem) -{ - int i, j, length = num_coefs4 * num_phases * (interp_order + 1); - real * result = mem->calloc(1,(size_t)length << LOG2_SIZEOF_REAL(core_flags)); - double fm1 = coefs[0], f1 = 0, f2 = 0; - - for (i = num_coefs - 1; i >= 0; --i) - for (j = num_phases - 1; j >= 0; --j) { - double f0 = fm1, b = 0, c = 0, d = 0; /* = 0 to kill compiler warning */ - int pos = i * num_phases + j - 1; - fm1 = pos > 0 ? coefs[pos - 1] * multiplier : 0; - switch (interp_order) { - case 1: b = f1 - f0; break; - case 2: b = f1 - (.5 * (f2+f0) - f1) - f0; c = .5 * (f2+f0) - f1; break; - case 3: c=.5*(f1+fm1)-f0;d=(1/6.)*(f2-f1+fm1-f0-4*c);b=f1-f0-d-c; break; - default: assert(!interp_order); - } - switch (core_flags & 3) { - case 0: if (WITH_CR32 ) STORE(coef , float ); break; - case 1: if (WITH_CR64 ) STORE(coef , double); break; - case 2: if (WITH_CR32S) STORE(coef4, float ); break; - default:if (WITH_CR64S) STORE(coef4, double); break; - } - f2 = f1, f1 = f0; - } - return result; -} - -#undef STORE -#undef coef_coef - -#define IS_FLOAT32 (WITH_CR32 || WITH_CR32S) && \ - (!(WITH_CR64 || WITH_CR64S) || sizeof_real == sizeof(float)) -#define WITH_FLOAT64 WITH_CR64 || WITH_CR64S - -static void dft_stage_fn(stage_t * p, fifo_t * output_fifo) -{ - real * output, * dft_out; - int i, j, num_in = max(0, fifo_occupancy(&p->fifo)); - rate_shared_t const * s = p->shared; - dft_filter_t const * f = &s->dft_filter[p->dft_filter_num]; - int const overlap = f->num_taps - 1; - - if (p->at.integer + p->L * num_in >= f->dft_length) { - fn_t const * const RDFT_CB = p->rdft_cb; - size_t const sizeof_real = sizeof(char) << LOG2_SIZEOF_REAL(p->core_flags); - div_t divd = div(f->dft_length - overlap - p->at.integer + p->L - 1, p->L); - real const * input = fifo_read_ptr(&p->fifo); - fifo_read(&p->fifo, divd.quot, NULL); - num_in -= divd.quot; - - output = fifo_reserve(output_fifo, f->dft_length); - dft_out = (p->core_flags & CORE_SIMD_DFT)? p->dft_out : output; - - if (lsx_is_power_of_2(p->L)) { /* F-domain */ - int portion = f->dft_length / p->L; - memcpy(dft_out, input, (unsigned)portion * sizeof_real); - rdft_oforward(portion, f->dft_forward_setup, dft_out, p->dft_scratch); - if (IS_FLOAT32) { -#define dft_out ((float *)dft_out) - for (i = portion + 2; i < (portion << 1); i += 2) /* Mirror image. */ - dft_out[i] = dft_out[(portion << 1) - i], - dft_out[i+1] = -dft_out[(portion << 1) - i + 1]; - dft_out[portion] = dft_out[1]; - dft_out[portion + 1] = 0; - dft_out[1] = dft_out[0]; -#undef dft_out - } - else if (WITH_FLOAT64) { -#define dft_out ((double *)dft_out) - for (i = portion + 2; i < (portion << 1); i += 2) /* Mirror image. */ - dft_out[i] = dft_out[(portion << 1) - i], - dft_out[i+1] = -dft_out[(portion << 1) - i + 1]; - dft_out[portion] = dft_out[1]; - dft_out[portion + 1] = 0; - dft_out[1] = dft_out[0]; -#undef dft_out - } - - for (portion <<= 1; i < f->dft_length; i += portion, portion <<= 1) { - memcpy((char *)dft_out + (size_t)i * sizeof_real, dft_out, (size_t)portion * sizeof_real); - if (IS_FLOAT32) - #define dft_out ((float *)dft_out) - dft_out[i + 1] = 0; - #undef dft_out - else if (WITH_FLOAT64) - #define dft_out ((double *)dft_out) - dft_out[i + 1] = 0; - #undef dft_out - } - if (p->step.integer > 0) - rdft_reorder_back(f->dft_length, f->dft_backward_setup, dft_out, p->dft_scratch); - } else { - if (p->L == 1) - memcpy(dft_out, input, (size_t)f->dft_length * sizeof_real); - else { - memset(dft_out, 0, (size_t)f->dft_length * sizeof_real); - if (IS_FLOAT32) - for (j = 0, i = p->at.integer; i < f->dft_length; ++j, i += p->L) - ((float *)dft_out)[i] = ((float *)input)[j]; - else if (WITH_FLOAT64) - for (j = 0, i = p->at.integer; i < f->dft_length; ++j, i += p->L) - ((double *)dft_out)[i] = ((double *)input)[j]; - p->at.integer = p->L - 1 - divd.rem; - } - if (p->step.integer > 0) - rdft_forward(f->dft_length, f->dft_forward_setup, dft_out, p->dft_scratch); - else - rdft_oforward(f->dft_length, f->dft_forward_setup, dft_out, p->dft_scratch); - } - - if (p->step.integer > 0) { - rdft_convolve(f->dft_length, f->dft_backward_setup, dft_out, f->coefs); - rdft_backward(f->dft_length, f->dft_backward_setup, dft_out, p->dft_scratch); - if ((p->core_flags & CORE_SIMD_DFT) && p->step.integer == 1) - memcpy(output, dft_out, (size_t)f->dft_length * sizeof_real); - if (p->step.integer != 1) { - if (IS_FLOAT32) - for (j = 0, i = p->remM; i < f->dft_length - overlap; ++j, - i += p->step.integer) - ((float *)output)[j] = ((float *)dft_out)[i]; - else if (WITH_FLOAT64) - for (j = 0, i = p->remM; i < f->dft_length - overlap; ++j, - i += p->step.integer) - ((double *)output)[j] = ((double *)dft_out)[i]; - p->remM = i - (f->dft_length - overlap); - fifo_trim_by(output_fifo, f->dft_length - j); - } - else fifo_trim_by(output_fifo, overlap); - } - else { /* F-domain */ - int m = -p->step.integer; - rdft_convolve_portion(f->dft_length >> m, dft_out, f->coefs); - rdft_obackward(f->dft_length >> m, f->dft_backward_setup, dft_out, p->dft_scratch); - if (p->core_flags & CORE_SIMD_DFT) - memcpy(output, dft_out, (size_t)(f->dft_length >> m) * sizeof_real); - fifo_trim_by(output_fifo, (((1 << m) - 1) * f->dft_length + overlap) >>m); - } - (void)RDFT_CB; - } - p->input_size = (f->dft_length - p->at.integer + p->L - 1) / p->L; -} - -/* Set to 4 x nearest power of 2 or half of that */ -/* if danger of causing too many cache misses. */ -static int set_dft_length(int num_taps, int min, int large) -{ - double d = log((double)num_taps) / log(2.); - return 1 << range_limit((int)(d + 2.77), min, max((int)(d + 1.77), large)); -} - -static void dft_stage_init( - unsigned instance, double Fp, double Fs, double Fn, double att, - double phase_response, stage_t * p, int L, int M, double * multiplier, - unsigned min_dft_size, unsigned large_dft_size, core_flags_t core_flags, - fn_t const * RDFT_CB) -{ - dft_filter_t * f = &p->shared->dft_filter[instance]; - int num_taps = 0, dft_length = f->dft_length, i, offset; - bool f_domain_m = abs(3-M) == 1 && Fs <= 1; - size_t const sizeof_real = sizeof(char) << LOG2_SIZEOF_REAL(core_flags); - - if (!dft_length) { - int k = phase_response == 50 && lsx_is_power_of_2(L) && Fn == L? L << 1 : 4; - double m, * h = lsx_design_lpf(Fp, Fs, Fn, att, &num_taps, -k, -1.); - - if (phase_response != 50) - lsx_fir_to_phase(&h, &num_taps, &f->post_peak, phase_response); - else f->post_peak = num_taps / 2; - - dft_length = set_dft_length(num_taps, (int)min_dft_size, (int)large_dft_size); - f->coefs = rdft_calloc((size_t)dft_length, sizeof_real); - offset = dft_length - num_taps + 1; - m = (1. / dft_length) * rdft_multiplier() * L * *multiplier; - if (IS_FLOAT32) for (i = 0; i < num_taps; ++i) - ((float *)f->coefs)[(i + offset) & (dft_length - 1)] =(float)(h[i] * m); - else if (WITH_FLOAT64) for (i = 0; i < num_taps; ++i) - ((double *)f->coefs)[(i + offset) & (dft_length - 1)] = h[i] * m; - free(h); - } - - if (rdft_flags() & RDFT_IS_SIMD) - p->dft_out = rdft_malloc(sizeof_real * (size_t)dft_length); - if (rdft_flags() & RDFT_NEEDS_SCRATCH) - p->dft_scratch = rdft_malloc(2 * sizeof_real * (size_t)dft_length); - - if (!f->dft_length) { - void * coef_setup = rdft_forward_setup(dft_length); - int Lp = lsx_is_power_of_2(L)? L : 1; - int Mp = f_domain_m? M : 1; - f->dft_forward_setup = rdft_forward_setup(dft_length / Lp); - f->dft_backward_setup = rdft_backward_setup(dft_length / Mp); - if (Mp == 1) - rdft_forward(dft_length, coef_setup, f->coefs, p->dft_scratch); - else - rdft_oforward(dft_length, coef_setup, f->coefs, p->dft_scratch); - rdft_delete_setup(coef_setup); - f->num_taps = num_taps; - f->dft_length = dft_length; - lsx_debug("fir_len=%i dft_length=%i Fp=%g Fs=%g Fn=%g att=%g %i/%i", - num_taps, dft_length, Fp, Fs, Fn, att, L, M); - } - *multiplier = 1; - p->out_in_ratio = (double)L / M; - p->core_flags = core_flags; - p->rdft_cb = RDFT_CB; - p->fn = dft_stage_fn; - p->preload = f->post_peak / L; - p->at.integer = f->post_peak % L; - p->L = L; - p->step.integer = f_domain_m? -M/2 : M; - p->dft_filter_num = instance; - p->block_len = f->dft_length - (f->num_taps - 1); - p->phase0 = p->at.integer / p->L; - p->input_size = (f->dft_length - p->at.integer + p->L - 1) / p->L; -} - -static struct half_fir_info const * find_half_fir( - struct half_fir_info const * firs, size_t len, double att) -{ - size_t i; - for (i = 0; i + 1 < len && att > firs[i].att; ++i); - return &firs[i]; -} - -#define have_pre_stage (preM * preL != 1) -#define have_arb_stage (arbM * arbL != 1) -#define have_post_stage (postM * postL != 1) - -#include "soxr.h" - -STATIC char const * _soxr_init( - rate_t * const p, /* Per audio channel. */ - rate_shared_t * const shared, /* By channels undergoing same rate change. */ - double const io_ratio, /* Input rate divided by output rate. */ - soxr_quality_spec_t const * const q_spec, - soxr_runtime_spec_t const * const r_spec, - double multiplier, /* Linear gain to apply during conversion. */ - cr_core_t const * const core, - core_flags_t const core_flags) -{ - size_t const sizeof_real = sizeof(char) << LOG2_SIZEOF_REAL(core_flags); - double const tolerance = 1 + 1e-5; - - double bits = q_spec->precision; - rolloff_t const rolloff = (rolloff_t)(q_spec->flags & 3); - int interpolator = (int)(r_spec->flags & 3) - 1; - double const Fp0 = q_spec->passband_end, Fs0 = q_spec->stopband_begin; - double const phase_response = q_spec->phase_response, tbw0 = Fs0-Fp0; - - bool const maintain_3dB_pt = !!(q_spec->flags & SOXR_MAINTAIN_3DB_PT); - double tbw_tighten = 1, alpha; - #define tighten(x) (Fs0-(Fs0-(x))*tbw_tighten) - - double arbM = io_ratio, Fn1, Fp1 = Fp0, Fs1 = Fs0, bits1 = min(bits,33); - double att = (bits1 + 1) * linear_to_dB(2.), attArb = att; /* +1: pass+stop */ - int preL = 1, preM = 1, shr = 0, arbL = 1, postL = 1, postM = 1; - bool upsample=false, rational=false, iOpt=!(r_spec->flags&SOXR_NOSMALLINTOPT); - bool lq_bits= (q_spec->flags & SOXR_PROMOTE_TO_LQ)? bits <= 16 : bits == 16; - bool lq_Fp0 = (q_spec->flags & SOXR_PROMOTE_TO_LQ)? Fp0<=lq_bw0 : Fp0==lq_bw0; - int n = 0, i, mode = lq_bits && rolloff == rolloff_medium? io_ratio > 1 || - phase_response != 50 || !lq_Fp0 || Fs0 != 1 : ((int)ceil(bits1) - 6) / 4; - struct half_fir_info const * half_fir_info; - stage_t * s; - - if (io_ratio < 1 && Fs0 - 1 > 1 - Fp0 / tolerance) - return "imaging greater than rolloff"; - if (.002 / tolerance > tbw0 || tbw0 > .5 * tolerance) - return "transition bandwidth not in [0.2,50] % of nyquist"; - if (.5 / tolerance > Fp0 || Fs0 > 1.5 * tolerance) - return "transition band not within [50,150] % of nyquist"; - if (bits!=0 && (15 > bits || bits > 33)) - return "precision not in [15,33] bits"; - if (io_ratio <= 0) - return "resampling factor not positive"; - if (0 > phase_response || phase_response > 100) - return "phase response not in [0=min-phase,100=max-phase] %"; - - p->core = core; - p->io_ratio = io_ratio; - if (bits!=0) while (!n++) { /* Determine stages: */ - int try, L, M, x, maxL = interpolator > 0? 1 : mode? 2048 : - (int)ceil(r_spec->coef_size_kbytes * 1000. / (U100_l * (int)sizeof_real)); - double d, epsilon = 0, frac; - upsample = arbM < 1; - for (i = (int)(.5 * arbM), shr = 0; i >>= 1; arbM *= .5, ++shr); - preM = upsample || (arbM > 1.5 && arbM < 2); - postM = 1 + (arbM > 1 && preM), arbM /= postM; - preL = 1 + (!preM && arbM < 2) + (upsample && mode), arbM *= preL; - if ((frac = arbM - (int)arbM)!=0) - epsilon = fabs(floor(frac * MULT32 + .5) / (frac * MULT32) - 1); - for (i = 1, rational = frac==0; i <= maxL && !rational; ++i) { - d = frac * i, try = (int)(d + .5); - if ((rational = fabs(try / d - 1) <= epsilon)) { /* No long doubles! */ - if (try == i) - arbM = ceil(arbM), shr += x = arbM > 3, arbM /= 1 + x; - else arbM = i * (int)arbM + try, arbL = i; - } - } - L = preL * arbL, M = (int)(arbM * postM), x = (L|M)&1, L >>= !x, M >>= !x; - if (iOpt && postL == 1 && (d = preL * arbL / arbM) > 4 && d != 5) { - for (postL = 4, i = (int)(d / 16); (i >>= 1) && postL < 256; postL <<= 1); - arbM = arbM * postL / arbL / preL, arbL = 1, n = 0; - } else if (rational && (max(L, M) < 3 + 2 * iOpt || L * M < 6 * iOpt)) - preL = L, preM = M, arbM = arbL = postM = 1; - if (!mode && (!rational || !n)) - ++mode, n = 0; - } - - p->num_stages = shr + have_pre_stage + have_arb_stage + have_post_stage; - if (!p->num_stages && multiplier != 1) { - bits = arbL = 0; /* Use cubic_stage in this case. */ - ++p->num_stages; - } - p->stages = calloc((size_t)p->num_stages + 1, sizeof(*p->stages)); - if (!p->stages) - return "out of memory"; - for (i = 0; i < p->num_stages; ++i) { - p->stages[i].num = i; - p->stages[i].shared = shared; - p->stages[i].input_size = 8192; - } - p->stages[0].is_input = true; - - alpha = postM / (io_ratio * (postL << 0)); - - if ((n = p->num_stages) > 1) { /* Att. budget: */ - if (have_arb_stage) - att += linear_to_dB(2.), attArb = att, --n; - att += linear_to_dB((double)n); - } - - half_fir_info = find_half_fir(core->half_firs, core->half_firs_len, att); - for (i = 0, s = p->stages; i < shr; ++i, ++s) { - s->fn = half_fir_info->fn; - s->coefs = half_fir_info->coefs; - s->n = half_fir_info->num_coefs; - s->pre_post = 4 * s->n; - s->preload = s->pre = s->pre_post >> 1; - } - - if (have_pre_stage) { - if (maintain_3dB_pt && have_post_stage) { /* Trans. bands overlapping. */ - double x = tbw0 * lsx_inv_f_resp(-3., att); - x = -lsx_f_resp(x / (max(2 * alpha - Fs0, alpha) - Fp0), att); - if (x > .035) { - tbw_tighten = ((4.3074e-3 - 3.9121e-4 * x) * x - .040009) * x + 1.0014; - lsx_debug("tbw_tighten=%g (%gdB)", tbw_tighten, x); - } - } - Fn1 = preM? max(preL, preM) : arbM / arbL; - dft_stage_init(0, tighten(Fp1), Fs1, Fn1, att, phase_response, s++, preL, - max(preM, 1), &multiplier, r_spec->log2_min_dft_size, - r_spec->log2_large_dft_size, core_flags, core->rdft_cb); - Fp1 /= Fn1, Fs1 /= Fn1; - } - - if (bits==0 && have_arb_stage) { /* `Quick' cubic arb stage: */ - s->fn = core->cubic_stage_fn; - s->mult = multiplier, multiplier = 1; - s->step.whole = (int64_t)(arbM * MULT32 + .5); - s->pre_post = max(3, s->step.integer); - s->preload = s->pre = 1; - s->out_in_ratio = MULT32 / (double)s->step.whole; - } - else if (have_arb_stage) { /* Higher quality arb stage: */ - static const float rolloffs[] = {-.01f, -.3f, 0, -.103f}; - poly_fir_t const * f = &core->poly_firs[6*(upsample+!!preM)+mode-!upsample]; - int order, num_coefs = (int)f->interp[0].scalar, phase_bits, phases; - size_t coefs_size; - double at, Fp = Fp1, Fs, Fn, mult = upsample? 1 : arbM / arbL; - poly_fir1_t const * f1; - - if (!upsample && preM) - Fn = 2 * mult, Fs = 3 + fabs(Fs1 - 1); - else Fn = 1, Fs = 2 - (mode? Fp1 + (Fs1 - Fp1) * .7 : Fs1); - - if (mode) - Fp = Fs - (Fs - Fp) / (1 - lsx_inv_f_resp(rolloffs[rolloff], attArb)); - - i = (interpolator < 0? !rational : max(interpolator, !rational)) - 1; - do { - f1 = &f->interp[++i]; - assert(f1->fn); - if (i) - arbM /= arbL, arbL = 1, rational = false; - phase_bits = (int)ceil(f1->scalar - log(mult)/log(2.)); - phases = !rational? (1 << phase_bits) : arbL; - if (f->interp[0].scalar==0) { - int phases0 = max(phases, 19), n0 = 0; - lsx_design_lpf(Fp, Fs, -Fn, attArb, &n0, phases0, f->beta); - num_coefs = n0 / phases0 + 1, num_coefs += num_coefs & !preM; - } - if ((num_coefs & 1) && rational && (arbL & 1)) - phases <<= 1, arbL <<= 1, arbM *= 2; - at = arbL * (s->phase0 = .5 * (num_coefs & 1)); - order = i + (i && mode > 4); - coefs_size = (size_t)(num_coefs4 * phases * (order+1)) * sizeof_real; - } while (interpolator < 0 && i < 2 && f->interp[i+1].fn && - coefs_size / 1000 > r_spec->coef_size_kbytes); - - if (!s->shared->poly_fir_coefs) { - int num_taps = num_coefs * phases - 1; - double * coefs = lsx_design_lpf( - Fp, Fs, Fn, attArb, &num_taps, phases, f->beta); - s->shared->poly_fir_coefs = prepare_poly_fir_coefs( - coefs, num_coefs, phases, order, multiplier, core_flags, &core->mem); - lsx_debug("fir_len=%i phases=%i coef_interp=%i size=%.3gk", - num_coefs, phases, order, (double)coefs_size / 1000.); - free(coefs); - } - multiplier = 1; - s->fn = f1->fn; - s->pre_post = num_coefs4 - 1; - s->preload = ((num_coefs - 1) >> 1) + (num_coefs4 - num_coefs); - s->n = num_coefs4; - s->phase_bits = phase_bits; - s->L = arbL; - s->use_hi_prec_clock = - mode>1 && (q_spec->flags & SOXR_HI_PREC_CLOCK) && !rational; -#if WITH_FLOAT_STD_PREC_CLOCK - if (order && !s->use_hi_prec_clock) { - s->at.flt = at; - s->step.flt = arbM; - s->out_in_ratio = (double)(arbL / s->step.flt); - } else -#endif - { - s->at.whole = (int64_t)(at * MULT32 + .5); -#if WITH_HI_PREC_CLOCK - if (s->use_hi_prec_clock) { - double M = arbM * MULT32; - s->at.fix.ls.parts.ms = 0x80000000ul; - s->step.whole = (int64_t)M; - M -= (double)s->step.whole; - M *= MULT32 * MULT32; - s->step.fix.ls.all = (uint64_t)M; - } else -#endif - s->step.whole = (int64_t)(arbM * MULT32 + .5); - s->out_in_ratio = MULT32 * arbL / (double)s->step.whole; - } - ++s; - } - - if (have_post_stage) - dft_stage_init(1, tighten(Fp0 / (upsample? alpha : 1)), upsample? max(2 - - Fs0 / alpha, 1) : Fs0, (double)max(postL, postM), att, phase_response, - s++, postL, postM, &multiplier, r_spec->log2_min_dft_size, - r_spec->log2_large_dft_size, core_flags, core->rdft_cb); - - lsx_debug("%g: >>%i %i/%i %i/%g %i/%i (%x)", 1/io_ratio, - shr, preL, preM, arbL, arbM, postL, postM, core_flags); - - for (i = 0, s = p->stages; i < p->num_stages; ++i, ++s) { - fifo_create(&s->fifo, (int)sizeof_real); - memset(fifo_reserve(&s->fifo, s->preload), 0, - sizeof_real * (size_t)s->preload); - lsx_debug_more("%5i|%-5i preload=%i remL=%i", - s->pre, s->pre_post-s->pre, s->preload, s->at.integer); - } - fifo_create(&s->fifo, (int)sizeof_real); - return 0; -} - -static bool stage_process(stage_t * stage, bool flushing) -{ - fifo_t * fifo = &stage->fifo; - bool done = false; - int want; - while (!done && (want = stage->input_size - fifo_occupancy(fifo)) > 0) { - if (stage->is_input) { - if (flushing) - memset(fifo_reserve(fifo, want), 0, fifo->item_size * (size_t)want); - else done = true; - } - else done = stage_process(stage - 1, flushing); - } - stage->fn(stage, &stage[1].fifo); - return done && fifo_occupancy(fifo) < stage->input_size; -} - -STATIC void _soxr_process(rate_t * p, size_t olen) -{ - int const n = p->flushing? min(-(int)p->samples_out, (int)olen) : (int)olen; - stage_t * stage = &p->stages[p->num_stages]; - fifo_t * fifo = &stage->fifo; - bool done = false; - while (!done && fifo_occupancy(fifo) < (int)n) - done = stage->is_input || stage_process(stage - 1, p->flushing); -} - -STATIC real * _soxr_input(rate_t * p, real const * samples, size_t n) -{ - if (p->flushing) - return 0; - p->samples_in += (int64_t)n; - return fifo_write(&p->stages[0].fifo, (int)n, samples); -} - -STATIC real const * _soxr_output(rate_t * p, real * samples, size_t * n0) -{ - fifo_t * fifo = &p->stages[p->num_stages].fifo; - int n = p->flushing? min(-(int)p->samples_out, (int)*n0) : (int)*n0; - p->samples_out += n = min(n, fifo_occupancy(fifo)); - return fifo_read(fifo, (int)(*n0 = (size_t)n), samples); -} - -STATIC void _soxr_flush(rate_t * p) -{ - if (p->flushing) return; - p->samples_out -= (int64_t)((double)p->samples_in / p->io_ratio + .5); - p->samples_in = 0; - p->flushing = true; -} - -STATIC void _soxr_close(rate_t * p) -{ - if (p->stages) { - fn_t const * const RDFT_CB = p->core->rdft_cb; - rate_shared_t * shared = p->stages[0].shared; - int i; - - for (i = 0; i <= p->num_stages; ++i) { - stage_t * s = &p->stages[i]; - rdft_free(s->dft_scratch); - rdft_free(s->dft_out); - fifo_delete(&s->fifo); - } - if (shared) { - for (i = 0; i < 2; ++i) { - dft_filter_t * f= &shared->dft_filter[i]; - rdft_free(f->coefs); - rdft_delete_setup(f->dft_forward_setup); - rdft_delete_setup(f->dft_backward_setup); - } - p->core->mem.free(shared->poly_fir_coefs); - memset(shared, 0, sizeof(*shared)); - } - free(p->stages); - (void)RDFT_CB; - } -} - -#if defined SOXR_LIB -STATIC double _soxr_delay(rate_t * p) -{ - return (double)p->samples_in / p->io_ratio - (double)p->samples_out; -} - -STATIC void _soxr_sizes(size_t * shared, size_t * channel) -{ - *shared = sizeof(rate_shared_t); - *channel = sizeof(rate_t); -} -#endif diff --git a/C/src/soxr-0.1.3/src/cr.h b/C/src/soxr-0.1.3/src/cr.h deleted file mode 100644 index d6e86379..00000000 --- a/C/src/soxr-0.1.3/src/cr.h +++ /dev/null @@ -1,178 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#if !defined soxr_cr_included -#define soxr_cr_included - -#define FIFO_SIZE_T int -#include "fifo.h" - -typedef void real; /* float or double */ -struct stage; -typedef void (* stage_fn_t)(struct stage * input, fifo_t * output); -typedef struct half_fir_info { - int num_coefs; - real const * coefs; - stage_fn_t fn, dfn; - float att; -} half_fir_info_t; -typedef struct {float scalar; stage_fn_t fn;} poly_fir1_t; -typedef struct {float beta; poly_fir1_t interp[3];} poly_fir_t; - -#define U100_l 42 -#define MULT32 (65536. * 65536.) - -/* Conceptually: coef_p is &coefs[num_phases][fir_len][interp_order+1]: */ -#define coef(coef_p, interp_order, fir_len, phase_num, coef_interp_num, fir_coef_num) (coef_p)[\ - (fir_len) * ((interp_order) + 1) * (phase_num) + \ - ((interp_order) + 1) * (fir_coef_num) + \ - ((interp_order) - (coef_interp_num))] - -/* Conceptually: coef_p is &coefs[num_phases][fir_len/4][interp_order+1][4]: */ -#define coef4(coef_p, interp_order, fir_len, phase_num, coef_interp_num, fir_coef_num) (coef_p)[\ - (fir_len) * ((interp_order) + 1) * (phase_num) + \ - ((interp_order) + 1) * ((fir_coef_num) & ~3) + \ - 4 * ((interp_order) - (coef_interp_num)) + \ - ((fir_coef_num) & 3)] - -typedef union { /* Int64 in parts */ - #if HAVE_BIGENDIAN - struct {int32_t ms; uint32_t ls;} parts; - #else - struct {uint32_t ls; int32_t ms;} parts; - #endif - int64_t all; -} int64p_t; - -typedef union { /* Uint64 in parts */ - #if HAVE_BIGENDIAN - struct {uint32_t ms, ls;} parts; - #else - struct {uint32_t ls, ms;} parts; - #endif - uint64_t all; -} uint64p_t; - -typedef struct { - int dft_length, num_taps, post_peak; - void * dft_forward_setup, * dft_backward_setup; - real * coefs; -} dft_filter_t; - -typedef struct { /* So generated filter coefs may be shared between channels */ - real * poly_fir_coefs; - dft_filter_t dft_filter[2]; -} rate_shared_t; - -typedef double float_step_t; /* Or long double or __float128. */ - -typedef union { /* Fixed point arithmetic */ - struct {uint64p_t ls; int64p_t ms;} fix; /* Hi-prec has ~96 bits. */ - float_step_t flt; -} step_t; - -#define integer fix.ms.parts.ms -#define fraction fix.ms.parts.ls -#define whole fix.ms.all - -#define CORE_DBL 1 -#define CORE_SIMD_POLY 2 -#define CORE_SIMD_HALF 4 -#define CORE_SIMD_DFT 8 -#define LOG2_SIZEOF_REAL(core_flags) (2 + ((core_flags) & 1)) - -typedef int core_flags_t; - -#if defined SOXR_LIB -#include "rdft_t.h" -#else -typedef void fn_t; -#endif - -typedef struct stage { - int num; - - /* Common to all stage types: */ - core_flags_t core_flags; - stage_fn_t fn; - fifo_t fifo; - int pre; /* Number of past samples to store */ - int pre_post; /* pre + number of future samples to store */ - int preload; /* Number of zero samples to pre-load the fifo */ - double out_in_ratio; /* For buffer management. */ - int input_size; - bool is_input; - - /* For a stage with variable (run-time generated) filter coefs: */ - fn_t const * rdft_cb; - rate_shared_t * shared; - unsigned dft_filter_num; /* Which, if any, of the 2 DFT filters to use */ - real * dft_scratch; - float * dft_out; - real const * coefs; - - /* For a stage with variable L/M: */ - step_t at, step; - bool use_hi_prec_clock; - int L, remM; - int n, phase_bits, block_len; - double mult, phase0; -} stage_t; - -#define stage_occupancy(s) max(0, fifo_occupancy(&(s)->fifo) - (s)->pre_post) -#define stage_read_p(s) ((sample_t *)fifo_read_ptr(&(s)->fifo) + (s)->pre) - -#define lq_bw0 (1385/2048.) /* ~.67625, FP exact. */ - -typedef enum {rolloff_small, rolloff_medium, rolloff_none} rolloff_t; - -typedef struct { - void * (* alloc)(size_t); - void * (* calloc)(size_t, size_t); - void (* free)(void *); -} alloc_t; - -typedef struct { - alloc_t mem; - half_fir_info_t const * half_firs; - size_t half_firs_len; - half_fir_info_t const * doub_firs; - size_t doub_firs_len; - stage_fn_t cubic_stage_fn; - poly_fir_t const * poly_firs; - fn_t * rdft_cb; -} cr_core_t; - -typedef struct rate rate_t; -struct rate { - cr_core_t const * core; - double io_ratio; - int64_t samples_in, samples_out; - int num_stages, flushing; - stage_t * stages; -}; - -#if defined SOXR_LIB - -#include "soxr.h" - -char const * _soxr_init( - rate_t * const p, /* Per audio channel. */ - rate_shared_t * const shared, /* Between channels (undergoing same rate change)*/ - double const io_ratio, /* Input rate divided by output rate. */ - soxr_quality_spec_t const * const q_spec, - soxr_runtime_spec_t const * const r_spec, - double multiplier, /* Linear gain to apply during conversion. 1 */ - cr_core_t const * const core, - core_flags_t const); - -void _soxr_process(struct rate * p, size_t olen); -real * _soxr_input(struct rate * p, real const * samples, size_t n); -real const * _soxr_output(struct rate * p, real * samples, size_t * n0); -void _soxr_flush(struct rate * p); -void _soxr_close(struct rate * p); -double _soxr_delay(struct rate * p); -void _soxr_sizes(size_t * shared, size_t * channel); -#endif - -#endif diff --git a/C/src/soxr-0.1.3/src/cr32.c b/C/src/soxr-0.1.3/src/cr32.c deleted file mode 100644 index b9eb264d..00000000 --- a/C/src/soxr-0.1.3/src/cr32.c +++ /dev/null @@ -1,8 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#define RATE_CB _soxr_rate32_cb -#define CORE_STR "cr32" - -#define CORE_TYPE 0 -#include "cr-core.c" diff --git a/C/src/soxr-0.1.3/src/cr32s.c b/C/src/soxr-0.1.3/src/cr32s.c deleted file mode 100644 index 5de2a433..00000000 --- a/C/src/soxr-0.1.3/src/cr32s.c +++ /dev/null @@ -1,8 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#define RATE_CB _soxr_rate32s_cb -#define CORE_STR "cr32s" - -#define CORE_TYPE (CORE_SIMD_POLY|CORE_SIMD_HALF|CORE_SIMD_DFT) -#include "cr-core.c" diff --git a/C/src/soxr-0.1.3/src/cr64.c b/C/src/soxr-0.1.3/src/cr64.c deleted file mode 100644 index 518cdd76..00000000 --- a/C/src/soxr-0.1.3/src/cr64.c +++ /dev/null @@ -1,8 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#define RATE_CB _soxr_rate64_cb -#define CORE_STR "cr64" - -#define CORE_TYPE CORE_DBL -#include "cr-core.c" diff --git a/C/src/soxr-0.1.3/src/cr64s.c b/C/src/soxr-0.1.3/src/cr64s.c deleted file mode 100644 index 5dcd6f10..00000000 --- a/C/src/soxr-0.1.3/src/cr64s.c +++ /dev/null @@ -1,8 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#define RATE_CB _soxr_rate64s_cb -#define CORE_STR "cr64s" - -#define CORE_TYPE (CORE_DBL|CORE_SIMD_POLY|CORE_SIMD_HALF|CORE_SIMD_DFT) -#include "cr-core.c" diff --git a/C/src/soxr-0.1.3/src/data-io.c b/C/src/soxr-0.1.3/src/data-io.c deleted file mode 100644 index fb616758..00000000 --- a/C/src/soxr-0.1.3/src/data-io.c +++ /dev/null @@ -1,223 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#include -#include -#include - -#include "data-io.h" -#include "internal.h" - - - -#define DEINTERLEAVE_FROM(T,flag) do { \ - unsigned i; \ - size_t j; \ - T const * src = *src0; \ - if (ch > 1) for (j = 0; j < n; ++j) \ - for (i = 0; i < ch; ++i) dest[i][j] = (DEINTERLEAVE_TO)*src++; \ - else if (flag) memcpy(dest[0], src, n * sizeof(T)), src = &src[n]; \ - else for (j = 0; j < n; dest[0][j++] = (DEINTERLEAVE_TO)*src++); \ - *src0 = src; \ -} while (0) - - - -#if WITH_CR64 || WITH_CR64S -void _soxr_deinterleave(double * * dest, /* Round/clipping not needed here */ - soxr_datatype_t data_type, void const * * src0, size_t n, unsigned ch) -{ -#define DEINTERLEAVE_TO double - switch (data_type & 3) { - case SOXR_FLOAT32: DEINTERLEAVE_FROM(float, 0); break; - case SOXR_FLOAT64: DEINTERLEAVE_FROM(double, 1); break; - case SOXR_INT32: DEINTERLEAVE_FROM(int32_t, 0); break; - case SOXR_INT16: DEINTERLEAVE_FROM(int16_t, 0); break; - default: break; - } -} -#endif - - - -#if WITH_CR32 || WITH_CR32S || WITH_VR32 -void _soxr_deinterleave_f(float * * dest, /* Round/clipping not needed here */ - soxr_datatype_t data_type, void const * * src0, size_t n, unsigned ch) -{ -#undef DEINTERLEAVE_TO -#define DEINTERLEAVE_TO float - switch (data_type & 3) { - case SOXR_FLOAT32: DEINTERLEAVE_FROM(float, 1); break; - case SOXR_FLOAT64: DEINTERLEAVE_FROM(double, 0); break; - case SOXR_INT32: DEINTERLEAVE_FROM(int32_t, 0); break; - case SOXR_INT16: DEINTERLEAVE_FROM(int16_t, 0); break; - default: break; - } -} -#endif - - - -#include "rint.h" - - - -#if defined FE_INVALID && defined FPU_RINT32 && defined __STDC_VERSION__ - #if __STDC_VERSION__ >= 199901L - #pragma STDC FENV_ACCESS ON - #endif -#endif - -#if WITH_CR64 || WITH_CR64S -#define FLOATX double - -#define LSX_RINT_CLIP_2 lsx_rint32_clip_2 -#define LSX_RINT_CLIP lsx_rint32_clip -#define RINT_CLIP rint32_clip -#define RINT rint32D -#if defined FPU_RINT32 - #define FPU_RINT -#endif -#define RINT_T int32_t -#define RINT_MAX 2147483647L -#include "rint-clip.h" - -#define LSX_RINT_CLIP_2 lsx_rint16_clip_2 -#define LSX_RINT_CLIP lsx_rint16_clip -#define RINT_CLIP rint16_clip -#define RINT rint16D -#if defined FPU_RINT16 - #define FPU_RINT -#endif -#define RINT_T int16_t -#define RINT_MAX 32767 -#include "rint-clip.h" - -#define LSX_RINT_CLIP_2 lsx_rint16_clip_2_dither -#define LSX_RINT_CLIP lsx_rint16_clip_dither -#define RINT_CLIP rint16_clip_dither -#define RINT rint16D -#if defined FPU_RINT16 - #define FPU_RINT -#endif -#define RINT_T int16_t -#define RINT_MAX 32767 -#define DITHER -#include "rint-clip.h" - -#undef FLOATX -#endif - - - -#if WITH_CR32 || WITH_CR32S || WITH_VR32 -#define FLOATX float - -#define LSX_RINT_CLIP_2 lsx_rint32_clip_2_f -#define LSX_RINT_CLIP lsx_rint32_clip_f -#define RINT_CLIP rint32_clip_f -#define RINT rint32F -#if defined FPU_RINT32 - #define FPU_RINT -#endif -#define RINT_T int32_t -#define RINT_MAX 2147483647L -#include "rint-clip.h" - -#define LSX_RINT_CLIP_2 lsx_rint16_clip_2_f -#define LSX_RINT_CLIP lsx_rint16_clip_f -#define RINT_CLIP rint16_clip_f -#define RINT rint16F -#if defined FPU_RINT16 - #define FPU_RINT -#endif -#define RINT_T int16_t -#define RINT_MAX 32767 -#include "rint-clip.h" - -#define LSX_RINT_CLIP_2 lsx_rint16_clip_2_dither_f -#define LSX_RINT_CLIP lsx_rint16_clip_dither_f -#define RINT_CLIP rint16_clip_dither_f -#define RINT rint16D -#if defined FPU_RINT16 - #define FPU_RINT -#endif -#define RINT_T int16_t -#define RINT_MAX 32767 -#define DITHER -#include "rint-clip.h" - -#undef FLOATX -#endif - -#if defined FE_INVALID && defined FPU_RINT32 && defined __STDC_VERSION__ - #if __STDC_VERSION__ >= 199901L - #pragma STDC FENV_ACCESS OFF - #endif -#endif - - - -#define INTERLEAVE_TO(T,flag) do { \ - unsigned i; \ - size_t j; \ - T * dest = *dest0; \ - if (ch > 1) \ - for (j = 0; j < n; ++j) for (i = 0; i < ch; ++i) *dest++ = (T)src[i][j]; \ - else if (flag) memcpy(dest, src[0], n * sizeof(T)), dest = &dest[n]; \ - else for (j = 0; j < n; *dest++ = (T)src[0][j++]); \ - *dest0 = dest; \ - return 0; \ -} while (0) - -#if WITH_CR64 || WITH_CR64S -size_t /* clips */ _soxr_interleave(soxr_datatype_t data_type, void * * dest0, - double const * const * src, size_t n, unsigned ch, unsigned long * seed) -{ - switch (data_type & 3) { - case SOXR_FLOAT32: INTERLEAVE_TO(float, 0); - case SOXR_FLOAT64: INTERLEAVE_TO(double, 1); - - case SOXR_INT32: if (ch == 1) - return lsx_rint32_clip(dest0, src[0], n); - return lsx_rint32_clip_2(dest0, src, ch, n); - - case SOXR_INT16: if (seed) { - if (ch == 1) - return lsx_rint16_clip_dither(dest0, src[0], n, seed); - return lsx_rint16_clip_2_dither(dest0, src, ch, n, seed); - } - if (ch == 1) - return lsx_rint16_clip(dest0, src[0], n); - return lsx_rint16_clip_2(dest0, src, ch, n); - default: break; - } - return 0; -} -#endif - -#if WITH_CR32 || WITH_CR32S || WITH_VR32 -size_t /* clips */ _soxr_interleave_f(soxr_datatype_t data_type, void * * dest0, - float const * const * src, size_t n, unsigned ch, unsigned long * seed) -{ - switch (data_type & 3) { - case SOXR_FLOAT32: INTERLEAVE_TO(float, 1); - case SOXR_FLOAT64: INTERLEAVE_TO(double, 0); - - case SOXR_INT32: if (ch == 1) - return lsx_rint32_clip_f(dest0, src[0], n); - return lsx_rint32_clip_2_f(dest0, src, ch, n); - - case SOXR_INT16: if (seed) { - if (ch == 1) - return lsx_rint16_clip_dither_f(dest0, src[0], n, seed); - return lsx_rint16_clip_2_dither_f(dest0, src, ch, n, seed); - } - if (ch == 1) - return lsx_rint16_clip_f(dest0, src[0], n); - return lsx_rint16_clip_2_f(dest0, src, ch, n); - default: break; - } - return 0; -} -#endif diff --git a/C/src/soxr-0.1.3/src/data-io.h b/C/src/soxr-0.1.3/src/data-io.h deleted file mode 100644 index 83a0a133..00000000 --- a/C/src/soxr-0.1.3/src/data-io.h +++ /dev/null @@ -1,39 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#if !defined soxr_data_io_included -#define soxr_data_io_included - -#include "soxr.h" - -void _soxr_deinterleave( - double * * dest, - soxr_datatype_t data_type, - void const * * src0, - size_t n, - unsigned ch); - -void _soxr_deinterleave_f( - float * * dest, - soxr_datatype_t data_type, - void const * * src0, - size_t n, - unsigned ch); - -size_t /* clips */ _soxr_interleave( - soxr_datatype_t data_type, - void * * dest, - double const * const * src, - size_t n, - unsigned ch, - unsigned long * seed); - -size_t /* clips */ _soxr_interleave_f( - soxr_datatype_t data_type, - void * * dest, - float const * const * src, - size_t n, - unsigned ch, - unsigned long * seed); - -#endif diff --git a/C/src/soxr-0.1.3/src/dbesi0.c b/C/src/soxr-0.1.3/src/dbesi0.c deleted file mode 100644 index 654216eb..00000000 --- a/C/src/soxr-0.1.3/src/dbesi0.c +++ /dev/null @@ -1,149 +0,0 @@ -/* Copyright(C) 1996 Takuya OOURA - -You may use, copy, modify this code for any purpose and -without fee. - -Package home: http://www.kurims.kyoto-u.ac.jp/~ooura/bessel.html -*/ - -#include "filter.h" -#define dbesi0 lsx_bessel_I_0 - -/* Bessel I_0(x) function in double precision */ - -#include - -double dbesi0(double x) -{ - int k; - double w, t, y; - static double a[65] = { - 8.5246820682016865877e-11, 2.5966600546497407288e-9, - 7.9689994568640180274e-8, 1.9906710409667748239e-6, - 4.0312469446528002532e-5, 6.4499871606224265421e-4, - 0.0079012345761930579108, 0.071111111109207045212, - 0.444444444444724909, 1.7777777777777532045, - 4.0000000000000011182, 3.99999999999999998, - 1.0000000000000000001, - 1.1520919130377195927e-10, 2.2287613013610985225e-9, - 8.1903951930694585113e-8, 1.9821560631611544984e-6, - 4.0335461940910133184e-5, 6.4495330974432203401e-4, - 0.0079013012611467520626, 0.071111038160875566622, - 0.44444450319062699316, 1.7777777439146450067, - 4.0000000132337935071, 3.9999999968569015366, - 1.0000000003426703174, - 1.5476870780515238488e-10, 1.2685004214732975355e-9, - 9.2776861851114223267e-8, 1.9063070109379044378e-6, - 4.0698004389917945832e-5, 6.4370447244298070713e-4, - 0.0079044749458444976958, 0.071105052411749363882, - 0.44445280640924755082, 1.7777694934432109713, - 4.0000055808824003386, 3.9999977081165740932, - 1.0000004333949319118, - 2.0675200625006793075e-10, -6.1689554705125681442e-10, - 1.2436765915401571654e-7, 1.5830429403520613423e-6, - 4.2947227560776583326e-5, 6.3249861665073441312e-4, - 0.0079454472840953930811, 0.070994327785661860575, - 0.44467219586283000332, 1.7774588182255374745, - 4.0003038986252717972, 3.9998233869142057195, - 1.0000472932961288324, - 2.7475684794982708655e-10, -3.8991472076521332023e-9, - 1.9730170483976049388e-7, 5.9651531561967674521e-7, - 5.1992971474748995357e-5, 5.7327338675433770752e-4, - 0.0082293143836530412024, 0.069990934858728039037, - 0.44726764292723985087, 1.7726685170014087784, - 4.0062907863712704432, 3.9952750700487845355, - 1.0016354346654179322 - }; - static double b[70] = { - 6.7852367144945531383e-8, 4.6266061382821826854e-7, - 6.9703135812354071774e-6, 7.6637663462953234134e-5, - 7.9113515222612691636e-4, 0.0073401204731103808981, - 0.060677114958668837046, 0.43994941411651569622, - 2.7420017097661750609, 14.289661921740860534, - 59.820609640320710779, 188.78998681199150629, - 399.8731367825601118, 427.56411572180478514, - 1.8042097874891098754e-7, 1.2277164312044637357e-6, - 1.8484393221474274861e-5, 2.0293995900091309208e-4, - 0.0020918539850246207459, 0.019375315654033949297, - 0.15985869016767185908, 1.1565260527420641724, - 7.1896341224206072113, 37.354773811947484532, - 155.80993164266268457, 489.5211371158540918, - 1030.9147225169564806, 1093.5883545113746958, - 4.8017305613187493564e-7, 3.261317843912380074e-6, - 4.9073137508166159639e-5, 5.3806506676487583755e-4, - 0.0055387918291051866561, 0.051223717488786549025, - 0.42190298621367914765, 3.0463625987357355872, - 18.895299447327733204, 97.915189029455461554, - 407.13940115493494659, 1274.3088990480582632, - 2670.9883037012547506, 2815.7166284662544712, - 1.2789926338424623394e-6, 8.6718263067604918916e-6, - 1.3041508821299929489e-4, 0.001428224737372747892, - 0.014684070635768789378, 0.13561403190404185755, - 1.1152592585977393953, 8.0387088559465389038, - 49.761318895895479206, 257.2684232313529138, - 1066.8543146269566231, 3328.3874581009636362, - 6948.8586598121634874, 7288.4893398212481055, - 3.409350368197032893e-6, 2.3079025203103376076e-5, - 3.4691373283901830239e-4, 0.003794994977222908545, - 0.038974209677945602145, 0.3594948380414878371, - 2.9522878893539528226, 21.246564609514287056, - 131.28727387146173141, 677.38107093296675421, - 2802.3724744545046518, 8718.5731420798254081, - 18141.348781638832286, 18948.925349296308859 - }; - static double c[45] = { - 2.5568678676452702768e-15, 3.0393953792305924324e-14, - 6.3343751991094840009e-13, 1.5041298011833009649e-11, - 4.4569436918556541414e-10, 1.746393051427167951e-8, - 1.0059224011079852317e-6, 1.0729838945088577089e-4, - 0.05150322693642527738, - 5.2527963991711562216e-15, 7.202118481421005641e-15, - 7.2561421229904797156e-13, 1.482312146673104251e-11, - 4.4602670450376245434e-10, 1.7463600061788679671e-8, - 1.005922609132234756e-6, 1.0729838937545111487e-4, - 0.051503226936437300716, - 1.3365917359358069908e-14, -1.2932643065888544835e-13, - 1.7450199447905602915e-12, 1.0419051209056979788e-11, - 4.58047881980598326e-10, 1.7442405450073548966e-8, - 1.0059461453281292278e-6, 1.0729837434500161228e-4, - 0.051503226940658446941, - 5.3771611477352308649e-14, -1.1396193006413731702e-12, - 1.2858641335221653409e-11, -5.9802086004570057703e-11, - 7.3666894305929510222e-10, 1.6731837150730356448e-8, - 1.0070831435812128922e-6, 1.0729733111203704813e-4, - 0.051503227360726294675, - 3.7819492084858931093e-14, -4.8600496888588034879e-13, - 1.6898350504817224909e-12, 4.5884624327524255865e-11, - 1.2521615963377513729e-10, 1.8959658437754727957e-8, - 1.0020716710561353622e-6, 1.073037119856927559e-4, - 0.05150322383300230775 - }; - - w = fabs(x); - if (w < 8.5) { - t = w * w * 0.0625; - k = 13 * ((int) t); - y = (((((((((((a[k] * t + a[k + 1]) * t + - a[k + 2]) * t + a[k + 3]) * t + a[k + 4]) * t + - a[k + 5]) * t + a[k + 6]) * t + a[k + 7]) * t + - a[k + 8]) * t + a[k + 9]) * t + a[k + 10]) * t + - a[k + 11]) * t + a[k + 12]; - } else if (w < 12.5) { - k = (int) w; - t = w - k; - k = 14 * (k - 8); - y = ((((((((((((b[k] * t + b[k + 1]) * t + - b[k + 2]) * t + b[k + 3]) * t + b[k + 4]) * t + - b[k + 5]) * t + b[k + 6]) * t + b[k + 7]) * t + - b[k + 8]) * t + b[k + 9]) * t + b[k + 10]) * t + - b[k + 11]) * t + b[k + 12]) * t + b[k + 13]; - } else { - t = 60 / w; - k = 9 * ((int) t); - y = ((((((((c[k] * t + c[k + 1]) * t + - c[k + 2]) * t + c[k + 3]) * t + c[k + 4]) * t + - c[k + 5]) * t + c[k + 6]) * t + c[k + 7]) * t + - c[k + 8]) * sqrt(t) * exp(w); - } - return y; -} diff --git a/C/src/soxr-0.1.3/src/dev32s.h b/C/src/soxr-0.1.3/src/dev32s.h deleted file mode 100644 index 7edae868..00000000 --- a/C/src/soxr-0.1.3/src/dev32s.h +++ /dev/null @@ -1,54 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#if !defined soxr_dev32s_included -#define soxr_dev32s_included - -#if defined __GNUC__ - #define SIMD_INLINE(T) static __inline T __attribute__((always_inline)) - #define vAlign __attribute__((aligned (16))) -#elif defined _MSC_VER - #define SIMD_INLINE(T) static __forceinline T - #define vAlign __declspec(align(16)) -#endif - -#if defined __x86_64__ || defined _M_X64 || defined i386 || defined _M_IX86 - -#include - -#define vZero() _mm_setzero_ps() -#define vSet1(a) _mm_set_ss(a) -#define vMul(a,b) _mm_mul_ps(a,b) -#define vAdd(a,b) _mm_add_ps(a,b) -#define vMac(a,b,c) vAdd(vMul(a,b),c) -#define vLds(a) _mm_set1_ps(a) -#define vLd(a) _mm_load_ps(a) -#define vLdu(a) _mm_loadu_ps(a) - -typedef __m128 v4_t; - -SIMD_INLINE(void) vStorSum(float * a, v4_t b) { - v4_t t = vAdd(_mm_movehl_ps(b, b), b); - _mm_store_ss(a, vAdd(t, _mm_shuffle_ps(t,t,1)));} - -#elif defined __arm__ - -#include - -#define vZero() vdupq_n_f32(0) -#define vMul(a,b) vmulq_f32(a,b) -#define vAdd(a,b) vaddq_f32(a,b) -#define vMac(a,b,c) vmlaq_f32(c,a,b) -#define vLds(a) vld1q_dup_f32(&(a)) -#define vLd(a) vld1q_f32(a) -#define vLdu(a) vld1q_f32(a) - -typedef float32x4_t v4_t; - -SIMD_INLINE(void) vStorSum(float * a, v4_t b) { - float32x2_t t = vadd_f32(vget_high_f32(b), vget_low_f32(b)); - *a = vget_lane_f32(vpadd_f32(t, t), 0);} - -#endif - -#endif diff --git a/C/src/soxr-0.1.3/src/dev64s.h b/C/src/soxr-0.1.3/src/dev64s.h deleted file mode 100644 index 4672210d..00000000 --- a/C/src/soxr-0.1.3/src/dev64s.h +++ /dev/null @@ -1,42 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#if !defined soxr_dev64s_included -#define soxr_dev64s_included - -#if defined __GNUC__ - #define SIMD_INLINE(T) static __inline T __attribute__((always_inline)) - #define vAlign __attribute__((aligned (32))) -#elif defined _MSC_VER - #define SIMD_INLINE(T) static __forceinline T - #define vAlign __declspec(align(32)) -#else - #define SIMD_INLINE(T) static __inline T -#endif - -#if defined __x86_64__ || defined _M_X64 || defined i386 || defined _M_IX86 - -#include - -#if defined __AVX__ - -#define vZero() _mm256_setzero_pd() -#define vSet1(a) _mm256_set_pd(0,0,0,a) -#define vMul(a,b) _mm256_mul_pd(a,b) -#define vAdd(a,b) _mm256_add_pd(a,b) -#define vMac(a,b,c) vAdd(vMul(a,b),c) /* Note: gcc -mfma will `fuse' these */ -#define vLds(a) _mm256_set1_pd(a) -#define vLd(a) _mm256_load_pd(a) -#define vLdu(a) _mm256_loadu_pd(a) - -typedef __m256d v4_t; - -SIMD_INLINE(void) vStorSum(double * a, v4_t b) { - b = _mm256_hadd_pd(b, _mm256_permute2f128_pd(b,b,1)); - _mm_store_sd(a, _mm256_castpd256_pd128(_mm256_hadd_pd(b,b)));} - -#endif - -#endif - -#endif diff --git a/C/src/soxr-0.1.3/src/fft4g.c b/C/src/soxr-0.1.3/src/fft4g.c deleted file mode 100644 index cf6293a0..00000000 --- a/C/src/soxr-0.1.3/src/fft4g.c +++ /dev/null @@ -1,1346 +0,0 @@ -/* Copyright Takuya OOURA, 1996-2001. - -You may use, copy, modify and distribute this code for any -purpose (include commercial use) and without fee. Please -refer to this package when you modify this code. - -Package home: http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html - -Fast Fourier/Cosine/Sine Transform - dimension :one - data length :power of 2 - decimation :frequency - radix :4, 2 - data :inplace - table :use -functions - cdft: Complex Discrete Fourier Transform - rdft: Real Discrete Fourier Transform - ddct: Discrete Cosine Transform - ddst: Discrete Sine Transform - dfct: Cosine Transform of RDFT (Real Symmetric DFT) - dfst: Sine Transform of RDFT (Real Anti-symmetric DFT) -function prototypes - void cdft(int, int, double *, int *, double *); - void rdft(int, int, double *, int *, double *); - void ddct(int, int, double *, int *, double *); - void ddst(int, int, double *, int *, double *); - void dfct(int, double *, double *, int *, double *); - void dfst(int, double *, double *, int *, double *); - - --------- Complex DFT (Discrete Fourier Transform) -------- - [definition] - - X[k] = sum_j=0^n-1 x[j]*exp(2*pi*i*j*k/n), 0<=k - X[k] = sum_j=0^n-1 x[j]*exp(-2*pi*i*j*k/n), 0<=k - ip[0] = 0; // first time only - cdft(2*n, 1, a, ip, w); - - ip[0] = 0; // first time only - cdft(2*n, -1, a, ip, w); - [parameters] - 2*n :data length (int) - n >= 1, n = power of 2 - a[0...2*n-1] :input/output data (double *) - input data - a[2*j] = Re(x[j]), - a[2*j+1] = Im(x[j]), 0<=j= 2+sqrt(n) - strictly, - length of ip >= - 2+(1<<(int)(log(n+0.5)/log(2))/2). - ip[0],ip[1] are pointers of the cos/sin table. - w[0...n/2-1] :cos/sin table (double *) - w[],ip[] are initialized if ip[0] == 0. - [remark] - Inverse of - cdft(2*n, -1, a, ip, w); - is - cdft(2*n, 1, a, ip, w); - for (j = 0; j <= 2 * n - 1; j++) { - a[j] *= 1.0 / n; - } - . - - --------- Real DFT / Inverse of Real DFT -------- - [definition] - RDFT - R[k] = sum_j=0^n-1 a[j]*cos(2*pi*j*k/n), 0<=k<=n/2 - I[k] = sum_j=0^n-1 a[j]*sin(2*pi*j*k/n), 0 IRDFT (excluding scale) - a[k] = (R[0] + R[n/2]*cos(pi*k))/2 + - sum_j=1^n/2-1 R[j]*cos(2*pi*j*k/n) + - sum_j=1^n/2-1 I[j]*sin(2*pi*j*k/n), 0<=k - ip[0] = 0; // first time only - rdft(n, 1, a, ip, w); - - ip[0] = 0; // first time only - rdft(n, -1, a, ip, w); - [parameters] - n :data length (int) - n >= 2, n = power of 2 - a[0...n-1] :input/output data (double *) - - output data - a[2*k] = R[k], 0<=k - input data - a[2*j] = R[j], 0<=j= 2+sqrt(n/2) - strictly, - length of ip >= - 2+(1<<(int)(log(n/2+0.5)/log(2))/2). - ip[0],ip[1] are pointers of the cos/sin table. - w[0...n/2-1] :cos/sin table (double *) - w[],ip[] are initialized if ip[0] == 0. - [remark] - Inverse of - rdft(n, 1, a, ip, w); - is - rdft(n, -1, a, ip, w); - for (j = 0; j <= n - 1; j++) { - a[j] *= 2.0 / n; - } - . - - --------- DCT (Discrete Cosine Transform) / Inverse of DCT -------- - [definition] - IDCT (excluding scale) - C[k] = sum_j=0^n-1 a[j]*cos(pi*j*(k+1/2)/n), 0<=k DCT - C[k] = sum_j=0^n-1 a[j]*cos(pi*(j+1/2)*k/n), 0<=k - ip[0] = 0; // first time only - ddct(n, 1, a, ip, w); - - ip[0] = 0; // first time only - ddct(n, -1, a, ip, w); - [parameters] - n :data length (int) - n >= 2, n = power of 2 - a[0...n-1] :input/output data (double *) - output data - a[k] = C[k], 0<=k= 2+sqrt(n/2) - strictly, - length of ip >= - 2+(1<<(int)(log(n/2+0.5)/log(2))/2). - ip[0],ip[1] are pointers of the cos/sin table. - w[0...n*5/4-1] :cos/sin table (double *) - w[],ip[] are initialized if ip[0] == 0. - [remark] - Inverse of - ddct(n, -1, a, ip, w); - is - a[0] *= 0.5; - ddct(n, 1, a, ip, w); - for (j = 0; j <= n - 1; j++) { - a[j] *= 2.0 / n; - } - . - - --------- DST (Discrete Sine Transform) / Inverse of DST -------- - [definition] - IDST (excluding scale) - S[k] = sum_j=1^n A[j]*sin(pi*j*(k+1/2)/n), 0<=k DST - S[k] = sum_j=0^n-1 a[j]*sin(pi*(j+1/2)*k/n), 0 - ip[0] = 0; // first time only - ddst(n, 1, a, ip, w); - - ip[0] = 0; // first time only - ddst(n, -1, a, ip, w); - [parameters] - n :data length (int) - n >= 2, n = power of 2 - a[0...n-1] :input/output data (double *) - - input data - a[j] = A[j], 0 - output data - a[k] = S[k], 0= 2+sqrt(n/2) - strictly, - length of ip >= - 2+(1<<(int)(log(n/2+0.5)/log(2))/2). - ip[0],ip[1] are pointers of the cos/sin table. - w[0...n*5/4-1] :cos/sin table (double *) - w[],ip[] are initialized if ip[0] == 0. - [remark] - Inverse of - ddst(n, -1, a, ip, w); - is - a[0] *= 0.5; - ddst(n, 1, a, ip, w); - for (j = 0; j <= n - 1; j++) { - a[j] *= 2.0 / n; - } - . - - --------- Cosine Transform of RDFT (Real Symmetric DFT) -------- - [definition] - C[k] = sum_j=0^n a[j]*cos(pi*j*k/n), 0<=k<=n - [usage] - ip[0] = 0; // first time only - dfct(n, a, t, ip, w); - [parameters] - n :data length - 1 (int) - n >= 2, n = power of 2 - a[0...n] :input/output data (double *) - output data - a[k] = C[k], 0<=k<=n - t[0...n/2] :work area (double *) - ip[0...*] :work area for bit reversal (int *) - length of ip >= 2+sqrt(n/4) - strictly, - length of ip >= - 2+(1<<(int)(log(n/4+0.5)/log(2))/2). - ip[0],ip[1] are pointers of the cos/sin table. - w[0...n*5/8-1] :cos/sin table (double *) - w[],ip[] are initialized if ip[0] == 0. - [remark] - Inverse of - a[0] *= 0.5; - a[n] *= 0.5; - dfct(n, a, t, ip, w); - is - a[0] *= 0.5; - a[n] *= 0.5; - dfct(n, a, t, ip, w); - for (j = 0; j <= n; j++) { - a[j] *= 2.0 / n; - } - . - - --------- Sine Transform of RDFT (Real Anti-symmetric DFT) -------- - [definition] - S[k] = sum_j=1^n-1 a[j]*sin(pi*j*k/n), 0= 2, n = power of 2 - a[0...n-1] :input/output data (double *) - output data - a[k] = S[k], 0= 2+sqrt(n/4) - strictly, - length of ip >= - 2+(1<<(int)(log(n/4+0.5)/log(2))/2). - ip[0],ip[1] are pointers of the cos/sin table. - w[0...n*5/8-1] :cos/sin table (double *) - w[],ip[] are initialized if ip[0] == 0. - [remark] - Inverse of - dfst(n, a, t, ip, w); - is - dfst(n, a, t, ip, w); - for (j = 1; j <= n - 1; j++) { - a[j] *= 2.0 / n; - } - . - - -Appendix : - The cos/sin table is recalculated when the larger table required. - w[] and ip[] are compatible with all routines. -*/ - - -#include "math-wrap.h" -#include "fft4g.h" - -#ifdef FFT4G_FLOAT - #define double float - #define one_half 0.5f - - #define sin(x) sinf(x) - #define cos(x) cosf(x) - #define atan(x) atanf(x) - - #define cdft lsx_cdft_f - #define rdft lsx_rdft_f - #define ddct lsx_ddct_f - #define ddst lsx_ddst_f - #define dfct lsx_dfct_f - #define dfst lsx_dfst_f -#else - #define one_half 0.5 - #define cdft lsx_cdft - #define rdft lsx_rdft - #define ddct lsx_ddct - #define ddst lsx_ddst - #define dfct lsx_dfct - #define dfst lsx_dfst -#endif - -static void bitrv2conj(int n, int *ip, double *a); -static void bitrv2(int n, int *ip, double *a); -static void cft1st(int n, double *a, double const *w); -static void cftbsub(int n, double *a, double const *w); -static void cftfsub(int n, double *a, double const *w); -static void cftmdl(int n, int l, double *a, double const *w); -static void dctsub(int n, double *a, int nc, double const *c); -static void dstsub(int n, double *a, int nc, double const *c); -static void makect(int nc, int *ip, double *c); -static void makewt(int nw, int *ip, double *w); -static void rftbsub(int n, double *a, int nc, double const *c); -static void rftfsub(int n, double *a, int nc, double const *c); - - -void cdft(int n, int isgn, double *a, int *ip, double *w) -{ - if (n > (ip[0] << 2)) { - makewt(n >> 2, ip, w); - } - if (n > 4) { - if (isgn >= 0) { - bitrv2(n, ip + 2, a); - cftfsub(n, a, w); - } else { - bitrv2conj(n, ip + 2, a); - cftbsub(n, a, w); - } - } else if (n == 4) { - cftfsub(n, a, w); - } -} - - -void rdft(int n, int isgn, double *a, int *ip, double *w) -{ - int nw, nc; - double xi; - - nw = ip[0]; - if (n > (nw << 2)) { - nw = n >> 2; - makewt(nw, ip, w); - } - nc = ip[1]; - if (n > (nc << 2)) { - nc = n >> 2; - makect(nc, ip, w + nw); - } - if (isgn >= 0) { - if (n > 4) { - bitrv2(n, ip + 2, a); - cftfsub(n, a, w); - rftfsub(n, a, nc, w + nw); - } else if (n == 4) { - cftfsub(n, a, w); - } - xi = a[0] - a[1]; - a[0] += a[1]; - a[1] = xi; - } else { - a[1] = one_half * (a[0] - a[1]); - a[0] -= a[1]; - if (n > 4) { - rftbsub(n, a, nc, w + nw); - bitrv2(n, ip + 2, a); - cftbsub(n, a, w); - } else if (n == 4) { - cftfsub(n, a, w); - } - } -} - - -void ddct(int n, int isgn, double *a, int *ip, double *w) -{ - int j, nw, nc; - double xr; - - nw = ip[0]; - if (n > (nw << 2)) { - nw = n >> 2; - makewt(nw, ip, w); - } - nc = ip[1]; - if (n > nc) { - nc = n; - makect(nc, ip, w + nw); - } - if (isgn < 0) { - xr = a[n - 1]; - for (j = n - 2; j >= 2; j -= 2) { - a[j + 1] = a[j] - a[j - 1]; - a[j] += a[j - 1]; - } - a[1] = a[0] - xr; - a[0] += xr; - if (n > 4) { - rftbsub(n, a, nc, w + nw); - bitrv2(n, ip + 2, a); - cftbsub(n, a, w); - } else if (n == 4) { - cftfsub(n, a, w); - } - } - dctsub(n, a, nc, w + nw); - if (isgn >= 0) { - if (n > 4) { - bitrv2(n, ip + 2, a); - cftfsub(n, a, w); - rftfsub(n, a, nc, w + nw); - } else if (n == 4) { - cftfsub(n, a, w); - } - xr = a[0] - a[1]; - a[0] += a[1]; - for (j = 2; j < n; j += 2) { - a[j - 1] = a[j] - a[j + 1]; - a[j] += a[j + 1]; - } - a[n - 1] = xr; - } -} - - -void ddst(int n, int isgn, double *a, int *ip, double *w) -{ - int j, nw, nc; - double xr; - - nw = ip[0]; - if (n > (nw << 2)) { - nw = n >> 2; - makewt(nw, ip, w); - } - nc = ip[1]; - if (n > nc) { - nc = n; - makect(nc, ip, w + nw); - } - if (isgn < 0) { - xr = a[n - 1]; - for (j = n - 2; j >= 2; j -= 2) { - a[j + 1] = -a[j] - a[j - 1]; - a[j] -= a[j - 1]; - } - a[1] = a[0] + xr; - a[0] -= xr; - if (n > 4) { - rftbsub(n, a, nc, w + nw); - bitrv2(n, ip + 2, a); - cftbsub(n, a, w); - } else if (n == 4) { - cftfsub(n, a, w); - } - } - dstsub(n, a, nc, w + nw); - if (isgn >= 0) { - if (n > 4) { - bitrv2(n, ip + 2, a); - cftfsub(n, a, w); - rftfsub(n, a, nc, w + nw); - } else if (n == 4) { - cftfsub(n, a, w); - } - xr = a[0] - a[1]; - a[0] += a[1]; - for (j = 2; j < n; j += 2) { - a[j - 1] = -a[j] - a[j + 1]; - a[j] -= a[j + 1]; - } - a[n - 1] = -xr; - } -} - - -void dfct(int n, double *a, double *t, int *ip, double *w) -{ - int j, k, l, m, mh, nw, nc; - double xr, xi, yr, yi; - - nw = ip[0]; - if (n > (nw << 3)) { - nw = n >> 3; - makewt(nw, ip, w); - } - nc = ip[1]; - if (n > (nc << 1)) { - nc = n >> 1; - makect(nc, ip, w + nw); - } - m = n >> 1; - yi = a[m]; - xi = a[0] + a[n]; - a[0] -= a[n]; - t[0] = xi - yi; - t[m] = xi + yi; - if (n > 2) { - mh = m >> 1; - for (j = 1; j < mh; j++) { - k = m - j; - xr = a[j] - a[n - j]; - xi = a[j] + a[n - j]; - yr = a[k] - a[n - k]; - yi = a[k] + a[n - k]; - a[j] = xr; - a[k] = yr; - t[j] = xi - yi; - t[k] = xi + yi; - } - t[mh] = a[mh] + a[n - mh]; - a[mh] -= a[n - mh]; - dctsub(m, a, nc, w + nw); - if (m > 4) { - bitrv2(m, ip + 2, a); - cftfsub(m, a, w); - rftfsub(m, a, nc, w + nw); - } else if (m == 4) { - cftfsub(m, a, w); - } - a[n - 1] = a[0] - a[1]; - a[1] = a[0] + a[1]; - for (j = m - 2; j >= 2; j -= 2) { - a[2 * j + 1] = a[j] + a[j + 1]; - a[2 * j - 1] = a[j] - a[j + 1]; - } - l = 2; - m = mh; - while (m >= 2) { - dctsub(m, t, nc, w + nw); - if (m > 4) { - bitrv2(m, ip + 2, t); - cftfsub(m, t, w); - rftfsub(m, t, nc, w + nw); - } else if (m == 4) { - cftfsub(m, t, w); - } - a[n - l] = t[0] - t[1]; - a[l] = t[0] + t[1]; - k = 0; - for (j = 2; j < m; j += 2) { - k += l << 2; - a[k - l] = t[j] - t[j + 1]; - a[k + l] = t[j] + t[j + 1]; - } - l <<= 1; - mh = m >> 1; - for (j = 0; j < mh; j++) { - k = m - j; - t[j] = t[m + k] - t[m + j]; - t[k] = t[m + k] + t[m + j]; - } - t[mh] = t[m + mh]; - m = mh; - } - a[l] = t[0]; - a[n] = t[2] - t[1]; - a[0] = t[2] + t[1]; - } else { - a[1] = a[0]; - a[2] = t[0]; - a[0] = t[1]; - } -} - - -void dfst(int n, double *a, double *t, int *ip, double *w) -{ - int j, k, l, m, mh, nw, nc; - double xr, xi, yr, yi; - - nw = ip[0]; - if (n > (nw << 3)) { - nw = n >> 3; - makewt(nw, ip, w); - } - nc = ip[1]; - if (n > (nc << 1)) { - nc = n >> 1; - makect(nc, ip, w + nw); - } - if (n > 2) { - m = n >> 1; - mh = m >> 1; - for (j = 1; j < mh; j++) { - k = m - j; - xr = a[j] + a[n - j]; - xi = a[j] - a[n - j]; - yr = a[k] + a[n - k]; - yi = a[k] - a[n - k]; - a[j] = xr; - a[k] = yr; - t[j] = xi + yi; - t[k] = xi - yi; - } - t[0] = a[mh] - a[n - mh]; - a[mh] += a[n - mh]; - a[0] = a[m]; - dstsub(m, a, nc, w + nw); - if (m > 4) { - bitrv2(m, ip + 2, a); - cftfsub(m, a, w); - rftfsub(m, a, nc, w + nw); - } else if (m == 4) { - cftfsub(m, a, w); - } - a[n - 1] = a[1] - a[0]; - a[1] = a[0] + a[1]; - for (j = m - 2; j >= 2; j -= 2) { - a[2 * j + 1] = a[j] - a[j + 1]; - a[2 * j - 1] = -a[j] - a[j + 1]; - } - l = 2; - m = mh; - while (m >= 2) { - dstsub(m, t, nc, w + nw); - if (m > 4) { - bitrv2(m, ip + 2, t); - cftfsub(m, t, w); - rftfsub(m, t, nc, w + nw); - } else if (m == 4) { - cftfsub(m, t, w); - } - a[n - l] = t[1] - t[0]; - a[l] = t[0] + t[1]; - k = 0; - for (j = 2; j < m; j += 2) { - k += l << 2; - a[k - l] = -t[j] - t[j + 1]; - a[k + l] = t[j] - t[j + 1]; - } - l <<= 1; - mh = m >> 1; - for (j = 1; j < mh; j++) { - k = m - j; - t[j] = t[m + k] + t[m + j]; - t[k] = t[m + k] - t[m + j]; - } - t[0] = t[m + mh]; - m = mh; - } - a[l] = t[0]; - } - a[0] = 0; -} - - -/* -------- initializing routines -------- */ - - -static void makewt(int nw, int *ip, double *w) -{ - int j, nwh; - double delta, x, y; - - ip[0] = nw; - ip[1] = 1; - if (nw > 2) { - nwh = nw >> 1; - delta = atan(1.0) / (double)nwh; - w[0] = 1; - w[1] = 0; - w[nwh] = cos(delta * (double)nwh); - w[nwh + 1] = w[nwh]; - if (nwh > 2) { - for (j = 2; j < nwh; j += 2) { - x = cos(delta * (double)j); - y = sin(delta * (double)j); - w[j] = x; - w[j + 1] = y; - w[nw - j] = y; - w[nw - j + 1] = x; - } - bitrv2(nw, ip + 2, w); - } - } -} - - -static void makect(int nc, int *ip, double *c) -{ - int j, nch; - double delta; - - ip[1] = nc; - if (nc > 1) { - nch = nc >> 1; - delta = atan(1.0) / (double)nch; - c[0] = cos(delta * (double)nch); - c[nch] = one_half * c[0]; - for (j = 1; j < nch; j++) { - c[j] = one_half * cos(delta * (double)j); - c[nc - j] = one_half * sin(delta * (double)j); - } - } -} - - -/* -------- child routines -------- */ - - -static void bitrv2(int n, int *ip0, double *a) -{ - int j, j1, k, k1, l, m, m2, ip[1024]; - double xr, xi, yr, yi; - - (void)ip0; - ip[0] = 0; - l = n; - m = 1; - while ((m << 3) < l) { - l >>= 1; - for (j = 0; j < m; j++) { - ip[m + j] = ip[j] + l; - } - m <<= 1; - } - m2 = 2 * m; - if ((m << 3) == l) { - for (k = 0; k < m; k++) { - for (j = 0; j < k; j++) { - j1 = 2 * j + ip[k]; - k1 = 2 * k + ip[j]; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += m2; - k1 += 2 * m2; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += m2; - k1 -= m2; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += m2; - k1 += 2 * m2; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - } - j1 = 2 * k + m2 + ip[k]; - k1 = j1 + m2; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - } - } else { - for (k = 1; k < m; k++) { - for (j = 0; j < k; j++) { - j1 = 2 * j + ip[k]; - k1 = 2 * k + ip[j]; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += m2; - k1 += m2; - xr = a[j1]; - xi = a[j1 + 1]; - yr = a[k1]; - yi = a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - } - } - } -} - - -static void bitrv2conj(int n, int *ip0, double *a) -{ - int j, j1, k, k1, l, m, m2, ip[512]; - double xr, xi, yr, yi; - - (void)ip0; - ip[0] = 0; - l = n; - m = 1; - while ((m << 3) < l) { - l >>= 1; - for (j = 0; j < m; j++) { - ip[m + j] = ip[j] + l; - } - m <<= 1; - } - m2 = 2 * m; - if ((m << 3) == l) { - for (k = 0; k < m; k++) { - for (j = 0; j < k; j++) { - j1 = 2 * j + ip[k]; - k1 = 2 * k + ip[j]; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += m2; - k1 += 2 * m2; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += m2; - k1 -= m2; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += m2; - k1 += 2 * m2; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - } - k1 = 2 * k + ip[k]; - a[k1 + 1] = -a[k1 + 1]; - j1 = k1 + m2; - k1 = j1 + m2; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - k1 += m2; - a[k1 + 1] = -a[k1 + 1]; - } - } else { - a[1] = -a[1]; - a[m2 + 1] = -a[m2 + 1]; - for (k = 1; k < m; k++) { - for (j = 0; j < k; j++) { - j1 = 2 * j + ip[k]; - k1 = 2 * k + ip[j]; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - j1 += m2; - k1 += m2; - xr = a[j1]; - xi = -a[j1 + 1]; - yr = a[k1]; - yi = -a[k1 + 1]; - a[j1] = yr; - a[j1 + 1] = yi; - a[k1] = xr; - a[k1 + 1] = xi; - } - k1 = 2 * k + ip[k]; - a[k1 + 1] = -a[k1 + 1]; - a[k1 + m2 + 1] = -a[k1 + m2 + 1]; - } - } -} - - -static void cftfsub(int n, double *a, double const *w) -{ - int j, j1, j2, j3, l; - double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; - - l = 2; - if (n > 8) { - cft1st(n, a, w); - l = 8; - while ((l << 2) < n) { - cftmdl(n, l, a, w); - l <<= 2; - } - } - if ((l << 2) == n) { - for (j = 0; j < l; j += 2) { - j1 = j + l; - j2 = j1 + l; - j3 = j2 + l; - x0r = a[j] + a[j1]; - x0i = a[j + 1] + a[j1 + 1]; - x1r = a[j] - a[j1]; - x1i = a[j + 1] - a[j1 + 1]; - x2r = a[j2] + a[j3]; - x2i = a[j2 + 1] + a[j3 + 1]; - x3r = a[j2] - a[j3]; - x3i = a[j2 + 1] - a[j3 + 1]; - a[j] = x0r + x2r; - a[j + 1] = x0i + x2i; - a[j2] = x0r - x2r; - a[j2 + 1] = x0i - x2i; - a[j1] = x1r - x3i; - a[j1 + 1] = x1i + x3r; - a[j3] = x1r + x3i; - a[j3 + 1] = x1i - x3r; - } - } else { - for (j = 0; j < l; j += 2) { - j1 = j + l; - x0r = a[j] - a[j1]; - x0i = a[j + 1] - a[j1 + 1]; - a[j] += a[j1]; - a[j + 1] += a[j1 + 1]; - a[j1] = x0r; - a[j1 + 1] = x0i; - } - } -} - - -static void cftbsub(int n, double *a, double const *w) -{ - int j, j1, j2, j3, l; - double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; - - l = 2; - if (n > 8) { - cft1st(n, a, w); - l = 8; - while ((l << 2) < n) { - cftmdl(n, l, a, w); - l <<= 2; - } - } - if ((l << 2) == n) { - for (j = 0; j < l; j += 2) { - j1 = j + l; - j2 = j1 + l; - j3 = j2 + l; - x0r = a[j] + a[j1]; - x0i = -a[j + 1] - a[j1 + 1]; - x1r = a[j] - a[j1]; - x1i = -a[j + 1] + a[j1 + 1]; - x2r = a[j2] + a[j3]; - x2i = a[j2 + 1] + a[j3 + 1]; - x3r = a[j2] - a[j3]; - x3i = a[j2 + 1] - a[j3 + 1]; - a[j] = x0r + x2r; - a[j + 1] = x0i - x2i; - a[j2] = x0r - x2r; - a[j2 + 1] = x0i + x2i; - a[j1] = x1r - x3i; - a[j1 + 1] = x1i - x3r; - a[j3] = x1r + x3i; - a[j3 + 1] = x1i + x3r; - } - } else { - for (j = 0; j < l; j += 2) { - j1 = j + l; - x0r = a[j] - a[j1]; - x0i = -a[j + 1] + a[j1 + 1]; - a[j] += a[j1]; - a[j + 1] = -a[j + 1] - a[j1 + 1]; - a[j1] = x0r; - a[j1 + 1] = x0i; - } - } -} - - -static void cft1st(int n, double *a, double const *w) -{ - int j, k1, k2; - double wk1r, wk1i, wk2r, wk2i, wk3r, wk3i; - double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; - - x0r = a[0] + a[2]; - x0i = a[1] + a[3]; - x1r = a[0] - a[2]; - x1i = a[1] - a[3]; - x2r = a[4] + a[6]; - x2i = a[5] + a[7]; - x3r = a[4] - a[6]; - x3i = a[5] - a[7]; - a[0] = x0r + x2r; - a[1] = x0i + x2i; - a[4] = x0r - x2r; - a[5] = x0i - x2i; - a[2] = x1r - x3i; - a[3] = x1i + x3r; - a[6] = x1r + x3i; - a[7] = x1i - x3r; - wk1r = w[2]; - x0r = a[8] + a[10]; - x0i = a[9] + a[11]; - x1r = a[8] - a[10]; - x1i = a[9] - a[11]; - x2r = a[12] + a[14]; - x2i = a[13] + a[15]; - x3r = a[12] - a[14]; - x3i = a[13] - a[15]; - a[8] = x0r + x2r; - a[9] = x0i + x2i; - a[12] = x2i - x0i; - a[13] = x0r - x2r; - x0r = x1r - x3i; - x0i = x1i + x3r; - a[10] = wk1r * (x0r - x0i); - a[11] = wk1r * (x0r + x0i); - x0r = x3i + x1r; - x0i = x3r - x1i; - a[14] = wk1r * (x0i - x0r); - a[15] = wk1r * (x0i + x0r); - k1 = 0; - for (j = 16; j < n; j += 16) { - k1 += 2; - k2 = 2 * k1; - wk2r = w[k1]; - wk2i = w[k1 + 1]; - wk1r = w[k2]; - wk1i = w[k2 + 1]; - wk3r = wk1r - 2 * wk2i * wk1i; - wk3i = 2 * wk2i * wk1r - wk1i; - x0r = a[j] + a[j + 2]; - x0i = a[j + 1] + a[j + 3]; - x1r = a[j] - a[j + 2]; - x1i = a[j + 1] - a[j + 3]; - x2r = a[j + 4] + a[j + 6]; - x2i = a[j + 5] + a[j + 7]; - x3r = a[j + 4] - a[j + 6]; - x3i = a[j + 5] - a[j + 7]; - a[j] = x0r + x2r; - a[j + 1] = x0i + x2i; - x0r -= x2r; - x0i -= x2i; - a[j + 4] = wk2r * x0r - wk2i * x0i; - a[j + 5] = wk2r * x0i + wk2i * x0r; - x0r = x1r - x3i; - x0i = x1i + x3r; - a[j + 2] = wk1r * x0r - wk1i * x0i; - a[j + 3] = wk1r * x0i + wk1i * x0r; - x0r = x1r + x3i; - x0i = x1i - x3r; - a[j + 6] = wk3r * x0r - wk3i * x0i; - a[j + 7] = wk3r * x0i + wk3i * x0r; - wk1r = w[k2 + 2]; - wk1i = w[k2 + 3]; - wk3r = wk1r - 2 * wk2r * wk1i; - wk3i = 2 * wk2r * wk1r - wk1i; - x0r = a[j + 8] + a[j + 10]; - x0i = a[j + 9] + a[j + 11]; - x1r = a[j + 8] - a[j + 10]; - x1i = a[j + 9] - a[j + 11]; - x2r = a[j + 12] + a[j + 14]; - x2i = a[j + 13] + a[j + 15]; - x3r = a[j + 12] - a[j + 14]; - x3i = a[j + 13] - a[j + 15]; - a[j + 8] = x0r + x2r; - a[j + 9] = x0i + x2i; - x0r -= x2r; - x0i -= x2i; - a[j + 12] = -wk2i * x0r - wk2r * x0i; - a[j + 13] = -wk2i * x0i + wk2r * x0r; - x0r = x1r - x3i; - x0i = x1i + x3r; - a[j + 10] = wk1r * x0r - wk1i * x0i; - a[j + 11] = wk1r * x0i + wk1i * x0r; - x0r = x1r + x3i; - x0i = x1i - x3r; - a[j + 14] = wk3r * x0r - wk3i * x0i; - a[j + 15] = wk3r * x0i + wk3i * x0r; - } -} - - -static void cftmdl(int n, int l, double *a, double const *w) -{ - int j, j1, j2, j3, k, k1, k2, m, m2; - double wk1r, wk1i, wk2r, wk2i, wk3r, wk3i; - double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; - - m = l << 2; - for (j = 0; j < l; j += 2) { - j1 = j + l; - j2 = j1 + l; - j3 = j2 + l; - x0r = a[j] + a[j1]; - x0i = a[j + 1] + a[j1 + 1]; - x1r = a[j] - a[j1]; - x1i = a[j + 1] - a[j1 + 1]; - x2r = a[j2] + a[j3]; - x2i = a[j2 + 1] + a[j3 + 1]; - x3r = a[j2] - a[j3]; - x3i = a[j2 + 1] - a[j3 + 1]; - a[j] = x0r + x2r; - a[j + 1] = x0i + x2i; - a[j2] = x0r - x2r; - a[j2 + 1] = x0i - x2i; - a[j1] = x1r - x3i; - a[j1 + 1] = x1i + x3r; - a[j3] = x1r + x3i; - a[j3 + 1] = x1i - x3r; - } - wk1r = w[2]; - for (j = m; j < l + m; j += 2) { - j1 = j + l; - j2 = j1 + l; - j3 = j2 + l; - x0r = a[j] + a[j1]; - x0i = a[j + 1] + a[j1 + 1]; - x1r = a[j] - a[j1]; - x1i = a[j + 1] - a[j1 + 1]; - x2r = a[j2] + a[j3]; - x2i = a[j2 + 1] + a[j3 + 1]; - x3r = a[j2] - a[j3]; - x3i = a[j2 + 1] - a[j3 + 1]; - a[j] = x0r + x2r; - a[j + 1] = x0i + x2i; - a[j2] = x2i - x0i; - a[j2 + 1] = x0r - x2r; - x0r = x1r - x3i; - x0i = x1i + x3r; - a[j1] = wk1r * (x0r - x0i); - a[j1 + 1] = wk1r * (x0r + x0i); - x0r = x3i + x1r; - x0i = x3r - x1i; - a[j3] = wk1r * (x0i - x0r); - a[j3 + 1] = wk1r * (x0i + x0r); - } - k1 = 0; - m2 = 2 * m; - for (k = m2; k < n; k += m2) { - k1 += 2; - k2 = 2 * k1; - wk2r = w[k1]; - wk2i = w[k1 + 1]; - wk1r = w[k2]; - wk1i = w[k2 + 1]; - wk3r = wk1r - 2 * wk2i * wk1i; - wk3i = 2 * wk2i * wk1r - wk1i; - for (j = k; j < l + k; j += 2) { - j1 = j + l; - j2 = j1 + l; - j3 = j2 + l; - x0r = a[j] + a[j1]; - x0i = a[j + 1] + a[j1 + 1]; - x1r = a[j] - a[j1]; - x1i = a[j + 1] - a[j1 + 1]; - x2r = a[j2] + a[j3]; - x2i = a[j2 + 1] + a[j3 + 1]; - x3r = a[j2] - a[j3]; - x3i = a[j2 + 1] - a[j3 + 1]; - a[j] = x0r + x2r; - a[j + 1] = x0i + x2i; - x0r -= x2r; - x0i -= x2i; - a[j2] = wk2r * x0r - wk2i * x0i; - a[j2 + 1] = wk2r * x0i + wk2i * x0r; - x0r = x1r - x3i; - x0i = x1i + x3r; - a[j1] = wk1r * x0r - wk1i * x0i; - a[j1 + 1] = wk1r * x0i + wk1i * x0r; - x0r = x1r + x3i; - x0i = x1i - x3r; - a[j3] = wk3r * x0r - wk3i * x0i; - a[j3 + 1] = wk3r * x0i + wk3i * x0r; - } - wk1r = w[k2 + 2]; - wk1i = w[k2 + 3]; - wk3r = wk1r - 2 * wk2r * wk1i; - wk3i = 2 * wk2r * wk1r - wk1i; - for (j = k + m; j < l + (k + m); j += 2) { - j1 = j + l; - j2 = j1 + l; - j3 = j2 + l; - x0r = a[j] + a[j1]; - x0i = a[j + 1] + a[j1 + 1]; - x1r = a[j] - a[j1]; - x1i = a[j + 1] - a[j1 + 1]; - x2r = a[j2] + a[j3]; - x2i = a[j2 + 1] + a[j3 + 1]; - x3r = a[j2] - a[j3]; - x3i = a[j2 + 1] - a[j3 + 1]; - a[j] = x0r + x2r; - a[j + 1] = x0i + x2i; - x0r -= x2r; - x0i -= x2i; - a[j2] = -wk2i * x0r - wk2r * x0i; - a[j2 + 1] = -wk2i * x0i + wk2r * x0r; - x0r = x1r - x3i; - x0i = x1i + x3r; - a[j1] = wk1r * x0r - wk1i * x0i; - a[j1 + 1] = wk1r * x0i + wk1i * x0r; - x0r = x1r + x3i; - x0i = x1i - x3r; - a[j3] = wk3r * x0r - wk3i * x0i; - a[j3 + 1] = wk3r * x0i + wk3i * x0r; - } - } -} - - -static void rftfsub(int n, double *a, int nc, double const *c) -{ - int j, k, kk, ks, m; - double wkr, wki, xr, xi, yr, yi; - - m = n >> 1; - ks = 2 * nc / m; - kk = 0; - for (j = 2; j < m; j += 2) { - k = n - j; - kk += ks; - wkr = one_half - c[nc - kk]; - wki = c[kk]; - xr = a[j] - a[k]; - xi = a[j + 1] + a[k + 1]; - yr = wkr * xr - wki * xi; - yi = wkr * xi + wki * xr; - a[j] -= yr; - a[j + 1] -= yi; - a[k] += yr; - a[k + 1] -= yi; - } -} - - -static void rftbsub(int n, double *a, int nc, double const *c) -{ - int j, k, kk, ks, m; - double wkr, wki, xr, xi, yr, yi; - - a[1] = -a[1]; - m = n >> 1; - ks = 2 * nc / m; - kk = 0; - for (j = 2; j < m; j += 2) { - k = n - j; - kk += ks; - wkr = one_half - c[nc - kk]; - wki = c[kk]; - xr = a[j] - a[k]; - xi = a[j + 1] + a[k + 1]; - yr = wkr * xr + wki * xi; - yi = wkr * xi - wki * xr; - a[j] -= yr; - a[j + 1] = yi - a[j + 1]; - a[k] += yr; - a[k + 1] = yi - a[k + 1]; - } - a[m + 1] = -a[m + 1]; -} - - -static void dctsub(int n, double *a, int nc, double const *c) -{ - int j, k, kk, ks, m; - double wkr, wki, xr; - - m = n >> 1; - ks = nc / n; - kk = 0; - for (j = 1; j < m; j++) { - k = n - j; - kk += ks; - wkr = c[kk] - c[nc - kk]; - wki = c[kk] + c[nc - kk]; - xr = wki * a[j] - wkr * a[k]; - a[j] = wkr * a[j] + wki * a[k]; - a[k] = xr; - } - a[m] *= c[0]; -} - - -static void dstsub(int n, double *a, int nc, double const *c) -{ - int j, k, kk, ks, m; - double wkr, wki, xr; - - m = n >> 1; - ks = nc / n; - kk = 0; - for (j = 1; j < m; j++) { - k = n - j; - kk += ks; - wkr = c[kk] - c[nc - kk]; - wki = c[kk] + c[nc - kk]; - xr = wki * a[k] - wkr * a[j]; - a[k] = wkr * a[k] + wki * a[j]; - a[j] = xr; - } - a[m] *= c[0]; -} diff --git a/C/src/soxr-0.1.3/src/fft4g.h b/C/src/soxr-0.1.3/src/fft4g.h deleted file mode 100644 index 0f906abc..00000000 --- a/C/src/soxr-0.1.3/src/fft4g.h +++ /dev/null @@ -1,23 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -void lsx_cdft(int, int, double *, int *, double *); -void lsx_rdft(int, int, double *, int *, double *); -void lsx_ddct(int, int, double *, int *, double *); -void lsx_ddst(int, int, double *, int *, double *); -void lsx_dfct(int, double *, double *, int *, double *); -void lsx_dfst(int, double *, double *, int *, double *); - -void lsx_cdft_f(int, int, float *, int *, float *); -void lsx_rdft_f(int, int, float *, int *, float *); -void lsx_ddct_f(int, int, float *, int *, float *); -void lsx_ddst_f(int, int, float *, int *, float *); -void lsx_dfct_f(int, float *, float *, int *, float *); -void lsx_dfst_f(int, float *, float *, int *, float *); - -#define dft_br_len(l) (2ul + (1ul << (int)(log(l / 2 + .5) / log(2.)) / 2)) -#define dft_sc_len(l) ((unsigned long)l / 2) - -/* Over-allocate h by 2 to use these macros */ -#define LSX_PACK(h, n) h[1] = h[n] -#define LSX_UNPACK(h, n) h[n] = h[1], h[n + 1] = h[1] = 0; diff --git a/C/src/soxr-0.1.3/src/fft4g32.c b/C/src/soxr-0.1.3/src/fft4g32.c deleted file mode 100644 index 7a31ba4b..00000000 --- a/C/src/soxr-0.1.3/src/fft4g32.c +++ /dev/null @@ -1,36 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#include -#include "filter.h" -#define FFT4G_FLOAT -#include "fft4g.c" -#include "soxr-config.h" - -#if WITH_CR32 -#include "rdft_t.h" -static void * null(void) {return 0;} -static void forward (int length, void * setup, double * H) {lsx_safe_rdft_f(length, 1, H); (void)setup;} -static void backward(int length, void * setup, double * H) {lsx_safe_rdft_f(length, -1, H); (void)setup;} -static int multiplier(void) {return 2;} -static void nothing(void) {} -static int flags(void) {return 0;} - -fn_t _soxr_rdft32_cb[] = { - (fn_t)null, - (fn_t)null, - (fn_t)nothing, - (fn_t)forward, - (fn_t)forward, - (fn_t)backward, - (fn_t)backward, - (fn_t)_soxr_ordered_convolve_f, - (fn_t)_soxr_ordered_partial_convolve_f, - (fn_t)multiplier, - (fn_t)nothing, - (fn_t)malloc, - (fn_t)calloc, - (fn_t)free, - (fn_t)flags, -}; -#endif diff --git a/C/src/soxr-0.1.3/src/fft4g32s.c b/C/src/soxr-0.1.3/src/fft4g32s.c deleted file mode 100644 index 8ce9726e..00000000 --- a/C/src/soxr-0.1.3/src/fft4g32s.c +++ /dev/null @@ -1,31 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#include "filter.h" -#include "util32s.h" -#include "rdft_t.h" - -static void * null(void) {return 0;} -static void nothing(void) {} -static void forward (int length, void * setup, float * H) {lsx_safe_rdft_f(length, 1, H); (void)setup;} -static void backward(int length, void * setup, float * H) {lsx_safe_rdft_f(length, -1, H); (void)setup;} -static int multiplier(void) {return 2;} -static int flags(void) {return RDFT_IS_SIMD;} - -fn_t _soxr_rdft32s_cb[] = { - (fn_t)null, - (fn_t)null, - (fn_t)nothing, - (fn_t)forward, - (fn_t)forward, - (fn_t)backward, - (fn_t)backward, - (fn_t)ORDERED_CONVOLVE_SIMD, - (fn_t)ORDERED_PARTIAL_CONVOLVE_SIMD, - (fn_t)multiplier, - (fn_t)nothing, - (fn_t)SIMD_ALIGNED_MALLOC, - (fn_t)SIMD_ALIGNED_CALLOC, - (fn_t)SIMD_ALIGNED_FREE, - (fn_t)flags, -}; diff --git a/C/src/soxr-0.1.3/src/fft4g64.c b/C/src/soxr-0.1.3/src/fft4g64.c deleted file mode 100644 index 0018516a..00000000 --- a/C/src/soxr-0.1.3/src/fft4g64.c +++ /dev/null @@ -1,35 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#include -#include "filter.h" -#include "fft4g.c" -#include "soxr-config.h" - -#if WITH_CR64 -static void * null(void) {return 0;} -static void nothing(void) {} -static void forward (int length, void * setup, double * H) {lsx_safe_rdft(length, 1, H); (void)setup;} -static void backward(int length, void * setup, double * H) {lsx_safe_rdft(length, -1, H); (void)setup;} -static int multiplier(void) {return 2;} -static int flags(void) {return 0;} - -typedef void (* fn_t)(void); -fn_t _soxr_rdft64_cb[] = { - (fn_t)null, - (fn_t)null, - (fn_t)nothing, - (fn_t)forward, - (fn_t)forward, - (fn_t)backward, - (fn_t)backward, - (fn_t)_soxr_ordered_convolve, - (fn_t)_soxr_ordered_partial_convolve, - (fn_t)multiplier, - (fn_t)nothing, - (fn_t)malloc, - (fn_t)calloc, - (fn_t)free, - (fn_t)flags, -}; -#endif diff --git a/C/src/soxr-0.1.3/src/fft4g_cache.h b/C/src/soxr-0.1.3/src/fft4g_cache.h deleted file mode 100644 index d776c16c..00000000 --- a/C/src/soxr-0.1.3/src/fft4g_cache.h +++ /dev/null @@ -1,92 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -static int * LSX_FFT_BR; -static DFT_FLOAT * LSX_FFT_SC; -static int FFT_LEN = -1; -static ccrw2_t FFT_CACHE_CCRW; - -void LSX_INIT_FFT_CACHE(void) -{ - if (FFT_LEN >= 0) - return; - assert(LSX_FFT_BR == NULL); - assert(LSX_FFT_SC == NULL); - assert(FFT_LEN == -1); - ccrw2_init(FFT_CACHE_CCRW); - FFT_LEN = 0; -} - -void LSX_CLEAR_FFT_CACHE(void) -{ - assert(FFT_LEN >= 0); - ccrw2_clear(FFT_CACHE_CCRW); - free(LSX_FFT_BR); - free(LSX_FFT_SC); - LSX_FFT_SC = NULL; - LSX_FFT_BR = NULL; - FFT_LEN = -1; -} - -static bool UPDATE_FFT_CACHE(int len) -{ - LSX_INIT_FFT_CACHE(); - assert(lsx_is_power_of_2(len)); - assert(FFT_LEN >= 0); - ccrw2_become_reader(FFT_CACHE_CCRW); - if (len > FFT_LEN) { - ccrw2_cease_reading(FFT_CACHE_CCRW); - ccrw2_become_writer(FFT_CACHE_CCRW); - if (len > FFT_LEN) { - int old_n = FFT_LEN; - FFT_LEN = len; - LSX_FFT_BR = realloc(LSX_FFT_BR, dft_br_len(FFT_LEN) * sizeof(*LSX_FFT_BR)); - LSX_FFT_SC = realloc(LSX_FFT_SC, dft_sc_len(FFT_LEN) * sizeof(*LSX_FFT_SC)); - if (!old_n) { - LSX_FFT_BR[0] = 0; -#if SOXR_LIB - atexit(LSX_CLEAR_FFT_CACHE); -#endif - } - return true; - } - ccrw2_cease_writing(FFT_CACHE_CCRW); - ccrw2_become_reader(FFT_CACHE_CCRW); - } - return false; -} - -static void DONE_WITH_FFT_CACHE(bool is_writer) -{ - if (is_writer) - ccrw2_cease_writing(FFT_CACHE_CCRW); - else ccrw2_cease_reading(FFT_CACHE_CCRW); -} - -void LSX_SAFE_RDFT(int len, int type, DFT_FLOAT * d) -{ - bool is_writer = UPDATE_FFT_CACHE(len); - LSX_RDFT(len, type, d, LSX_FFT_BR, LSX_FFT_SC); - DONE_WITH_FFT_CACHE(is_writer); -} - -void LSX_SAFE_CDFT(int len, int type, DFT_FLOAT * d) -{ - bool is_writer = UPDATE_FFT_CACHE(len); - LSX_CDFT(len, type, d, LSX_FFT_BR, LSX_FFT_SC); - DONE_WITH_FFT_CACHE(is_writer); -} - -#undef UPDATE_FFT_CACHE -#undef LSX_SAFE_RDFT -#undef LSX_SAFE_CDFT -#undef LSX_RDFT -#undef LSX_INIT_FFT_CACHE -#undef LSX_FFT_SC -#undef LSX_FFT_BR -#undef LSX_CLEAR_FFT_CACHE -#undef LSX_CDFT -#undef FFT_LEN -#undef FFT_CACHE_CCRW -#undef DONE_WITH_FFT_CACHE -#undef DFT_FLOAT diff --git a/C/src/soxr-0.1.3/src/fifo.h b/C/src/soxr-0.1.3/src/fifo.h deleted file mode 100644 index 33af9fe6..00000000 --- a/C/src/soxr-0.1.3/src/fifo.h +++ /dev/null @@ -1,125 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#ifndef soxr_fifo_included -#define soxr_fifo_included - -#if !defined FIFO_SIZE_T -#define FIFO_SIZE_T size_t -#endif - -#if !defined FIFO_REALLOC -#include - #define FIFO_REALLOC(a,b,c) realloc(a,b) - #undef FIFO_FREE - #define FIFO_FREE free - #undef FIFO_MALLOC - #define FIFO_MALLOC malloc -#endif - -typedef struct { - char * data; - size_t allocation; /* Number of bytes allocated for data. */ - size_t item_size; /* Size of each item in data */ - size_t begin; /* Offset of the first byte to read. */ - size_t end; /* 1 + Offset of the last byte byte to read. */ -} fifo_t; - -#if !defined FIFO_MIN - #define FIFO_MIN 0x4000 -#endif - -#if !defined UNUSED - #define UNUSED -#endif - -UNUSED static void fifo_clear(fifo_t * f) -{ - f->end = f->begin = 0; -} - -UNUSED static void * fifo_reserve(fifo_t * f, FIFO_SIZE_T n0) -{ - size_t n = (size_t)n0; - n *= f->item_size; - - if (f->begin == f->end) - fifo_clear(f); - - while (1) { - if (f->end + n <= f->allocation) { - void *p = f->data + f->end; - - f->end += n; - return p; - } - if (f->begin > FIFO_MIN) { - memmove(f->data, f->data + f->begin, f->end - f->begin); - f->end -= f->begin; - f->begin = 0; - continue; - } - f->data = FIFO_REALLOC(f->data, f->allocation + n, f->allocation); - f->allocation += n; - if (!f->data) - return 0; - } -} - -UNUSED static void * fifo_write(fifo_t * f, FIFO_SIZE_T n0, void const * data) -{ - size_t n = (size_t)n0; - void * s = fifo_reserve(f, n0); - if (data) - memcpy(s, data, n * f->item_size); - return s; -} - -UNUSED static void fifo_trim_to(fifo_t * f, FIFO_SIZE_T n0) -{ - size_t n = (size_t)n0; - n *= f->item_size; - f->end = f->begin + n; -} - -UNUSED static void fifo_trim_by(fifo_t * f, FIFO_SIZE_T n0) -{ - size_t n = (size_t)n0; - n *= f->item_size; - f->end -= n; -} - -UNUSED static FIFO_SIZE_T fifo_occupancy(fifo_t * f) -{ - return (FIFO_SIZE_T)((f->end - f->begin) / f->item_size); -} - -UNUSED static void * fifo_read(fifo_t * f, FIFO_SIZE_T n0, void * data) -{ - size_t n = (size_t)n0; - char * ret = f->data + f->begin; - n *= f->item_size; - if (n > (f->end - f->begin)) - return NULL; - if (data) - memcpy(data, ret, (size_t)n); - f->begin += n; - return ret; -} - -#define fifo_read_ptr(f) fifo_read(f, (FIFO_SIZE_T)0, NULL) - -UNUSED static void fifo_delete(fifo_t * f) -{ - FIFO_FREE(f->data); -} - -UNUSED static int fifo_create(fifo_t * f, FIFO_SIZE_T item_size) -{ - f->item_size = (size_t)item_size; - f->allocation = FIFO_MIN; - fifo_clear(f); - return !(f->data = FIFO_MALLOC(f->allocation)); -} - -#endif diff --git a/C/src/soxr-0.1.3/src/filter.c b/C/src/soxr-0.1.3/src/filter.c deleted file mode 100644 index 019d24d9..00000000 --- a/C/src/soxr-0.1.3/src/filter.c +++ /dev/null @@ -1,277 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#include "filter.h" - -#include "math-wrap.h" -#include -#include -#include - -#include "fft4g.h" -#include "ccrw2.h" - -#if 1 || WITH_CR64 || WITH_CR64S /* Always need this, for lsx_fir_to_phase. */ -#define DFT_FLOAT double -#define DONE_WITH_FFT_CACHE done_with_fft_cache -#define FFT_CACHE_CCRW fft_cache_ccrw -#define FFT_LEN fft_len -#define LSX_CDFT lsx_cdft -#define LSX_CLEAR_FFT_CACHE lsx_clear_fft_cache -#define LSX_FFT_BR lsx_fft_br -#define LSX_FFT_SC lsx_fft_sc -#define LSX_INIT_FFT_CACHE lsx_init_fft_cache -#define LSX_RDFT lsx_rdft -#define LSX_SAFE_CDFT lsx_safe_cdft -#define LSX_SAFE_RDFT lsx_safe_rdft -#define UPDATE_FFT_CACHE update_fft_cache -#include "fft4g_cache.h" -#endif - -#if (WITH_CR32 && !AVCODEC_FOUND) || (WITH_CR32S && !AVCODEC_FOUND && !WITH_PFFFT) -#define DFT_FLOAT float -#define DONE_WITH_FFT_CACHE done_with_fft_cache_f -#define FFT_CACHE_CCRW fft_cache_ccrw_f -#define FFT_LEN fft_len_f -#define LSX_CDFT lsx_cdft_f -#define LSX_CLEAR_FFT_CACHE lsx_clear_fft_cache_f -#define LSX_FFT_BR lsx_fft_br_f -#define LSX_FFT_SC lsx_fft_sc_f -#define LSX_INIT_FFT_CACHE lsx_init_fft_cache_f -#define LSX_RDFT lsx_rdft_f -#define LSX_SAFE_CDFT lsx_safe_cdft_f -#define LSX_SAFE_RDFT lsx_safe_rdft_f -#define UPDATE_FFT_CACHE update_fft_cache_f -#include "fft4g_cache.h" -#endif - -#if WITH_CR64 || WITH_CR64S || !SOXR_LIB -#define DFT_FLOAT double -#define ORDERED_CONVOLVE lsx_ordered_convolve -#define ORDERED_PARTIAL_CONVOLVE lsx_ordered_partial_convolve -#include "rdft.h" -#endif - -#if WITH_CR32 -#define DFT_FLOAT float -#define ORDERED_CONVOLVE lsx_ordered_convolve_f -#define ORDERED_PARTIAL_CONVOLVE lsx_ordered_partial_convolve_f -#include "rdft.h" -#endif - -double lsx_kaiser_beta(double att, double tr_bw) -{ - if (att >= 60) { - static const double coefs[][4] = { - {-6.784957e-10,1.02856e-05,0.1087556,-0.8988365+.001}, - {-6.897885e-10,1.027433e-05,0.10876,-0.8994658+.002}, - {-1.000683e-09,1.030092e-05,0.1087677,-0.9007898+.003}, - {-3.654474e-10,1.040631e-05,0.1087085,-0.8977766+.006}, - {8.106988e-09,6.983091e-06,0.1091387,-0.9172048+.015}, - {9.519571e-09,7.272678e-06,0.1090068,-0.9140768+.025}, - {-5.626821e-09,1.342186e-05,0.1083999,-0.9065452+.05}, - {-9.965946e-08,5.073548e-05,0.1040967,-0.7672778+.085}, - {1.604808e-07,-5.856462e-05,0.1185998,-1.34824+.1}, - {-1.511964e-07,6.363034e-05,0.1064627,-0.9876665+.18}, - }; - double realm = log(tr_bw/.0005)/log(2.); - double const * c0 = coefs[range_limit( (int)realm, 0, (int)array_length(coefs)-1)]; - double const * c1 = coefs[range_limit(1+(int)realm, 0, (int)array_length(coefs)-1)]; - double b0 = ((c0[0]*att + c0[1])*att + c0[2])*att + c0[3]; - double b1 = ((c1[0]*att + c1[1])*att + c1[2])*att + c1[3]; - return b0 + (b1 - b0) * (realm - (int)realm); - } - if (att > 50 ) return .1102 * (att - 8.7); - if (att > 20.96) return .58417 * pow(att -20.96, .4) + .07886 * (att - 20.96); - return 0; -} - -double * lsx_make_lpf( - int num_taps, double Fc, double beta, double rho, double scale) -{ - int i, m = num_taps - 1; - double * h = malloc((size_t)num_taps * sizeof(*h)); - double mult = scale / lsx_bessel_I_0(beta), mult1 = 1 / (.5 * m + rho); - assert(Fc >= 0 && Fc <= 1); - lsx_debug("make_lpf(n=%i Fc=%.7g beta=%g rho=%g scale=%g)", - num_taps, Fc, beta, rho, scale); - - if (h) for (i = 0; i <= m / 2; ++i) { - double z = i - .5 * m, x = z * M_PI, y = z * mult1; - h[i] = x!=0? sin(Fc * x) / x : Fc; - h[i] *= lsx_bessel_I_0(beta * sqrt(1 - y * y)) * mult; - if (m - i != i) - h[m - i] = h[i]; - } - return h; -} - -void lsx_kaiser_params(double att, double Fc, double tr_bw, double * beta, int * num_taps) -{ - *beta = *beta < 0? lsx_kaiser_beta(att, tr_bw * .5 / Fc): *beta; - att = att < 60? (att - 7.95) / (2.285 * M_PI * 2) : - ((.0007528358-1.577737e-05**beta)**beta+.6248022)**beta+.06186902; - *num_taps = !*num_taps? (int)ceil(att/tr_bw + 1) : *num_taps; -} - -double * lsx_design_lpf( - double Fp, /* End of pass-band */ - double Fs, /* Start of stop-band */ - double Fn, /* Nyquist freq; e.g. 0.5, 1, PI */ - double att, /* Stop-band attenuation in dB */ - int * num_taps, /* 0: value will be estimated */ - int k, /* >0: number of phases; <0: num_taps = 1 (mod -k) */ - double beta) /* <0: value will be estimated */ -{ - int n = *num_taps, phases = max(k, 1), modulo = max(-k, 1); - double tr_bw, Fc, rho = phases == 1? .5 : att < 120? .63 : .75; - - lsx_debug_more("./sinctest %-12.7g %-12.7g %g 0 %-5g %i %i 50 %g %g -4 >1", - Fp, Fs, Fn, att, *num_taps, k, beta, rho); - - Fp /= fabs(Fn), Fs /= fabs(Fn); /* Normalise to Fn = 1 */ - tr_bw = .5 * (Fs - Fp); /* Transition band-width: 6dB to stop points */ - tr_bw /= phases, Fs /= phases; - tr_bw = min(tr_bw, .5 * Fs); - Fc = Fs - tr_bw; - assert(Fc - tr_bw >= 0); - lsx_kaiser_params(att, Fc, tr_bw, &beta, num_taps); - if (!n) - *num_taps = phases > 1? *num_taps / phases * phases + phases - 1 : - (*num_taps + modulo - 2) / modulo * modulo + 1; - return Fn < 0? 0 : lsx_make_lpf(*num_taps, Fc, beta, rho, (double)phases); -} - -static double safe_log(double x) -{ - assert(x >= 0); - if (x!=0) - return log(x); - lsx_debug("log(0)"); - return -26; -} - -void lsx_fir_to_phase(double * * h, int * len, int * post_len, double phase) -{ - double * pi_wraps, * work, phase1 = (phase > 50 ? 100 - phase : phase) / 50; - int i, work_len, begin, end, imp_peak = 0, peak = 0; - double imp_sum = 0, peak_imp_sum = 0; - double prev_angle2 = 0, cum_2pi = 0, prev_angle1 = 0, cum_1pi = 0; - - for (i = *len, work_len = 2 * 2 * 8; i > 1; work_len <<= 1, i >>= 1); - - work = calloc((size_t)work_len + 2, sizeof(*work)); /* +2: (UN)PACK */ - pi_wraps = malloc((((size_t)work_len + 2) / 2) * sizeof(*pi_wraps)); - - memcpy(work, *h, (size_t)*len * sizeof(*work)); - lsx_safe_rdft(work_len, 1, work); /* Cepstral: */ - LSX_UNPACK(work, work_len); - - for (i = 0; i <= work_len; i += 2) { - double angle = atan2(work[i + 1], work[i]); - double detect = 2 * M_PI; - double delta = angle - prev_angle2; - double adjust = detect * ((delta < -detect * .7) - (delta > detect * .7)); - prev_angle2 = angle; - cum_2pi += adjust; - angle += cum_2pi; - detect = M_PI; - delta = angle - prev_angle1; - adjust = detect * ((delta < -detect * .7) - (delta > detect * .7)); - prev_angle1 = angle; - cum_1pi += fabs(adjust); /* fabs for when 2pi and 1pi have combined */ - pi_wraps[i >> 1] = cum_1pi; - - work[i] = safe_log(sqrt(sqr(work[i]) + sqr(work[i + 1]))); - work[i + 1] = 0; - } - LSX_PACK(work, work_len); - lsx_safe_rdft(work_len, -1, work); - for (i = 0; i < work_len; ++i) work[i] *= 2. / work_len; - - for (i = 1; i < work_len / 2; ++i) { /* Window to reject acausal components */ - work[i] *= 2; - work[i + work_len / 2] = 0; - } - lsx_safe_rdft(work_len, 1, work); - - for (i = 2; i < work_len; i += 2) /* Interpolate between linear & min phase */ - work[i + 1] = phase1 * i / work_len * pi_wraps[work_len >> 1] + - (1 - phase1) * (work[i + 1] + pi_wraps[i >> 1]) - pi_wraps[i >> 1]; - - work[0] = exp(work[0]), work[1] = exp(work[1]); - for (i = 2; i < work_len; i += 2) { - double x = exp(work[i]); - work[i ] = x * cos(work[i + 1]); - work[i + 1] = x * sin(work[i + 1]); - } - - lsx_safe_rdft(work_len, -1, work); - for (i = 0; i < work_len; ++i) work[i] *= 2. / work_len; - - /* Find peak pos. */ - for (i = 0; i <= (int)(pi_wraps[work_len >> 1] / M_PI + .5); ++i) { - imp_sum += work[i]; - if (fabs(imp_sum) > fabs(peak_imp_sum)) { - peak_imp_sum = imp_sum; - peak = i; - } - if (work[i] > work[imp_peak]) /* For debug check only */ - imp_peak = i; - } - while (peak && fabs(work[peak-1]) > fabs(work[peak]) && work[peak-1] * work[peak] > 0) - --peak; - - if (phase1==0) - begin = 0; - else if (phase1 == 1) - begin = peak - *len / 2; - else { - begin = (int)((.997 - (2 - phase1) * .22) * *len + .5); - end = (int)((.997 + (0 - phase1) * .22) * *len + .5); - begin = peak - (begin & ~3); - end = peak + 1 + ((end + 3) & ~3); - *len = end - begin; - *h = realloc(*h, (size_t)*len * sizeof(**h)); - } - for (i = 0; i < *len; ++i) (*h)[i] = - work[(begin + (phase > 50 ? *len - 1 - i : i) + work_len) & (work_len - 1)]; - *post_len = phase > 50 ? peak - begin : begin + *len - (peak + 1); - - lsx_debug("nPI=%g peak-sum@%i=%g (val@%i=%g); len=%i post=%i (%g%%)", - pi_wraps[work_len >> 1] / M_PI, peak, peak_imp_sum, imp_peak, - work[imp_peak], *len, *post_len, 100 - 100. * *post_len / (*len - 1)); - free(pi_wraps), free(work); -} - -#define F_x(F,expr) static double F(double x) {return expr;} -F_x(sinePhi, ((2.0517e-07*x-1.1303e-04)*x+.023154)*x+.55924 ) -F_x(sinePsi, ((9.0667e-08*x-5.6114e-05)*x+.013658)*x+1.0977 ) -F_x(sinePow, log(.5)/log(sin(x*.5)) ) -#define dB_to_linear(x) exp((x) * (M_LN10 * 0.05)) - -double lsx_f_resp(double t, double a) -{ - double x; - if (t > (a <= 160? .8 : .82)) { - double a1 = a+15; - double p = .00035*a+.375; - double w = 1/(1-.597)*asin(pow((a1-10.6)/a1,1/p)); - double c = 1+asin(pow(1-a/a1,1/p))/w; - return a1*(pow(sin((c-t)*w),p)-1); - } - if (t > .5) - x = sinePsi(a), x = pow(sin((1-t) * x), sinePow(x)); - else - x = sinePhi(a), x = 1 - pow(sin(t * x), sinePow(x)); - return linear_to_dB(x); -} - -double lsx_inv_f_resp(double drop, double a) -{ - double x = sinePhi(a), s; - drop = dB_to_linear(drop); - s = drop > .5 ? 1 - drop : drop; - x = asin(pow(s, 1/sinePow(x))) / x; - return drop > .5? x : 1 -x; -} diff --git a/C/src/soxr-0.1.3/src/filter.h b/C/src/soxr-0.1.3/src/filter.h deleted file mode 100644 index ccb3ba83..00000000 --- a/C/src/soxr-0.1.3/src/filter.h +++ /dev/null @@ -1,44 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#if !defined soxr_filter_included -#define soxr_filter_included - -#include "aliases.h" - -double lsx_bessel_I_0(double x); -void lsx_init_fft_cache(void); -void lsx_clear_fft_cache(void); -void lsx_init_fft_cache_f(void); -void lsx_clear_fft_cache_f(void); -#define lsx_is_power_of_2(x) !(x < 2 || (x & (x - 1))) -void lsx_safe_rdft(int len, int type, double * d); -void lsx_safe_cdft(int len, int type, double * d); -void lsx_safe_rdft_f(int len, int type, float * d); -void lsx_safe_cdft_f(int len, int type, float * d); -void lsx_ordered_convolve(int n, void * not_used, double * a, const double * b); -void lsx_ordered_convolve_f(int n, void * not_used, float * a, const float * b); -void lsx_ordered_partial_convolve(int n, double * a, const double * b); -void lsx_ordered_partial_convolve_f(int n, float * a, const float * b); - -double lsx_kaiser_beta(double att, double tr_bw); -double * lsx_make_lpf(int num_taps, double Fc, double beta, double rho, - double scale); -void lsx_kaiser_params(double att, double Fc, double tr_bw, double * beta, int * num_taps); -double * lsx_design_lpf( - double Fp, /* End of pass-band */ - double Fs, /* Start of stop-band */ - double Fn, /* Nyquist freq; e.g. 0.5, 1, PI; < 0: dummy run */ - double att, /* Stop-band attenuation in dB */ - int * num_taps, /* 0: value will be estimated */ - int k, /* >0: number of phases; <0: num_taps = 1 (mod -k) */ - double beta); /* <0: value will be estimated */ - -void lsx_fir_to_phase(double * * h, int * len, - int * post_len, double phase0); - -double lsx_f_resp(double t, double a); -double lsx_inv_f_resp(double drop, double a); -#define lsx_to_3dB(a) (1 - lsx_inv_f_resp(-3., a)) - -#endif diff --git a/C/src/soxr-0.1.3/src/half-coefs.h b/C/src/soxr-0.1.3/src/half-coefs.h deleted file mode 100644 index a5a0882b..00000000 --- a/C/src/soxr-0.1.3/src/half-coefs.h +++ /dev/null @@ -1,75 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#if defined __GNUC__ - #pragma GCC system_header -#elif defined __SUNPRO_C - #pragma disable_warn -#elif defined _MSC_VER - #pragma warning(push, 1) -#endif - -#if CORE_TYPE & CORE_SIMD_HALF - #define VALIGN vAlign -#else - #define VALIGN -#endif - -#if !(CORE_TYPE & CORE_SIMD_HALF) -static VALIGN const sample_t half_fir_coefs_7[] = { - 3.1062656496657370e-01, -8.4998810699955796e-02, 3.4007044621123500e-02, --1.2839903789829387e-02, 3.9899380181723145e-03, -8.9355202017945374e-04, - 1.0918292424806546e-04, -}; -#endif - -static VALIGN const sample_t half_fir_coefs_8[] = { - 3.1154652365332069e-01, -8.7344917685739543e-02, 3.6814458353637280e-02, --1.5189204581464479e-02, 5.4540855610738801e-03, -1.5643862626630416e-03, - 3.1816575906323303e-04, -3.4799449225005688e-05, -}; - -static VALIGN const sample_t half_fir_coefs_9[] = { - 3.1227034755311189e-01, -8.9221517147969526e-02, 3.9139704015071934e-02, --1.7250558515852023e-02, 6.8589440230476112e-03, -2.3045049636430419e-03, - 6.0963740543348963e-04, -1.1323803957431231e-04, 1.1197769991000046e-05, -}; - -#if CORE_TYPE & CORE_DBL -static VALIGN const sample_t half_fir_coefs_10[] = { - 3.1285456012000523e-01, -9.0756740799292787e-02, 4.1096398104193160e-02, --1.9066319572525220e-02, 8.1840569787684902e-03, -3.0766876176359834e-03, - 9.6396524429277980e-04, -2.3585679989922018e-04, 4.0252189026627833e-05, --3.6298196342497932e-06, -}; - -static VALIGN const sample_t half_fir_coefs_11[] = { - 3.1333588822574199e-01, -9.2035898673019811e-02, 4.2765169698406408e-02, --2.0673580894964429e-02, 9.4225426824512421e-03, -3.8563379950013192e-03, - 1.3634742159642453e-03, -3.9874150714431009e-04, 9.0586723632664806e-05, --1.4285617244076783e-05, 1.1834642946400529e-06, -}; - -static VALIGN const sample_t half_fir_coefs_12[] = { - 3.1373928463345568e-01, -9.3118180335301962e-02, 4.4205005881659098e-02, --2.2103860986973051e-02, 1.0574689371162864e-02, -4.6276428065385065e-03, - 1.7936153397572132e-03, -5.9617527051353237e-04, 1.6314517495669067e-04, --3.4555126770115446e-05, 5.0617615610782593e-06, -3.8768958592971409e-07, -}; - -static VALIGN const sample_t half_fir_coefs_13[] = { - 3.1408224847888910e-01, -9.4045836332667387e-02, 4.5459878763259978e-02, --2.3383369012219993e-02, 1.1644273044890753e-02, -5.3806714579057013e-03, - 2.2429072878264022e-03, -8.2204347506606424e-04, 2.5724946477840893e-04, --6.6072709864248668e-05, 1.3099163296288644e-05, -1.7907147069136000e-06, - 1.2750825595240592e-07, -}; -#endif - -#undef VALIGN - -#if defined __SUNPRO_C - #pragma enable_warn -#elif defined _MSC_VER - #pragma warning(pop) -#endif diff --git a/C/src/soxr-0.1.3/src/half-fir.h b/C/src/soxr-0.1.3/src/half-fir.h deleted file mode 100644 index 782be1bc..00000000 --- a/C/src/soxr-0.1.3/src/half-fir.h +++ /dev/null @@ -1,61 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -/* Decimate by 2 using a FIR with odd length (LEN). */ -/* Input must be preceded and followed by LEN >> 1 samples. */ - -#define COEFS ((sample_t const *)p->coefs) - -#if SIMD_SSE - #define BEGINNING v4_t sum, q1, q2, t - #define ____ \ - q1 = _mm_shuffle_ps(t=vLdu(input+2*j),vLdu(input+2*j+4),_MM_SHUFFLE(3,1,3,1)); \ - q2 = _mm_shuffle_ps(vLdu(input-2*j-4),vLdu(input-2*j-8),_MM_SHUFFLE(1,3,1,3)); \ - sum = vAdd(j? sum : vMul(vSet1(.5), t), vMul(vAdd(q1, q2), vLd(COEFS+j))); \ - j += 4; - #define __ \ - q1 = _mm_shuffle_ps(vLdu(input+2*j), vLdu(input-2*j-4), _MM_SHUFFLE(1,3,3,1)); \ - q2 = _mm_loadl_pi(q2, (__m64*)(COEFS+j)), q2 = _mm_movelh_ps(q2, q2); \ - sum = vAdd(sum, vMul(q1, q2)); \ - j += 2; - #define _ \ - q1 = _mm_add_ss(_mm_load_ss(input+2*j+1), _mm_load_ss(input-2*j-1)); \ - sum = _mm_add_ss(sum, _mm_mul_ss(q1, _mm_load_ss(COEFS+j))); \ - ++j; - #define END vStorSum(output+i, sum) -/* #elif SIMD_AVX; No good solution found. */ -/* #elif SIMD_NEON; No need: gcc -O3 does a good job by itself. */ -#else - #define BEGINNING sample_t sum = input[0] * .5f - #define ____ __ __ - #define __ _ _ - #define _ sum += (input[-(2*j +1)] + input[(2*j +1)]) * COEFS[j], ++j; - #define END output[i] = sum -#endif - - - -static void FUNCTION_H(stage_t * p, fifo_t * output_fifo) -{ - sample_t const * __restrict input = stage_read_p(p); - int num_in = min(stage_occupancy(p), p->input_size); - int i, num_out = (num_in + 1) >> 1; - sample_t * __restrict output = fifo_reserve(output_fifo, num_out); - - for (i = 0; i < num_out; ++i, input += 2) { - int j = 0; - BEGINNING; CONVOLVE; END; - } - fifo_read(&p->fifo, 2 * num_out, NULL); -} - - - -#undef _ -#undef __ -#undef ____ -#undef BEGINNING -#undef END -#undef COEFS -#undef CONVOLVE -#undef FUNCTION_H diff --git a/C/src/soxr-0.1.3/src/internal.h b/C/src/soxr-0.1.3/src/internal.h deleted file mode 100644 index 08924d50..00000000 --- a/C/src/soxr-0.1.3/src/internal.h +++ /dev/null @@ -1,84 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#if !defined soxr_internal_included -#define soxr_internal_included - -#include "std-types.h" - - - -#undef min -#undef max -#define min(a, b) ((a) <= (b) ? (a) : (b)) -#define max(a, b) ((a) >= (b) ? (a) : (b)) - - - -#define range_limit(x, lower, upper) (min(max(x, lower), upper)) -#define linear_to_dB(x) (log10(x) * 20) -#define array_length(a) (sizeof(a)/sizeof(a[0])) -#if !defined AL -#define AL(a) array_length(a) -#endif -#define iAL(a) (int)AL(a) -#define sqr(a) ((a) * (a)) - - - -#if defined __GNUC__ - #define UNUSED __attribute__ ((unused)) -#else - #define UNUSED -#endif - - - -#if !WITH_DEV_TRACE - #ifdef __GNUC__ - void lsx_dummy(char const *, ...); - #else - static __inline void lsx_dummy(char const * x, ...) {} - #endif - #define lsx_debug if(0) lsx_dummy - #define lsx_debug_more lsx_debug -#else - extern int _soxr_trace_level; - void _soxr_trace(char const * fmt, ...); - #define lsx_debug if (_soxr_trace_level > 0) _soxr_trace - #define lsx_debug_more if (_soxr_trace_level > 1) _soxr_trace -#endif - - - -/* soxr_quality_spec_t.flags: */ - -#define SOXR_ROLLOFF_LSR2Q 3u /* Reserved for internal use. */ -#define SOXR_ROLLOFF_MASK 3u /* For masking these bits. */ -#define SOXR_MAINTAIN_3DB_PT 4u /* Reserved for internal use. */ -#define SOXR_PROMOTE_TO_LQ 64u /* Reserved for internal use. */ - - - -/* soxr_runtime_spec_t.flags: */ - -#define SOXR_STRICT_BUFFERING 4u /* Reserved for future use. */ -#define SOXR_NOSMALLINTOPT 8u /* For test purposes only. */ - - - -/* soxr_quality_spec recipe: */ - -#define SOXR_PRECISIONQ 11 /* Quality specified by the precision parameter. */ - -#define SOXR_PHASE_MASK 0x30 /* For masking these bits. */ - - - -/* soxr_quality_spec flags: */ - -#define RESET_ON_CLEAR (1u<<31) - - - -#endif diff --git a/C/src/soxr-0.1.3/src/math-wrap.h b/C/src/soxr-0.1.3/src/math-wrap.h deleted file mode 100644 index 8a526f13..00000000 --- a/C/src/soxr-0.1.3/src/math-wrap.h +++ /dev/null @@ -1,31 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#if !defined soxr_math_wrap_included -#define soxr_math_wrap_included - -#include - -#if defined __STRICT_ANSI__ - #define sinf(x) (float)sin ((double)(x)) - #define cosf(x) (float)cos ((double)(x)) - #define atanf(x) (float)atan((double)(x)) -#endif - -#if !defined M_PI - #define M_PI 3.141592653589793238462643383279502884 -#endif - -#if !defined M_LN10 - #define M_LN10 2.302585092994045684017991454684364208 -#endif - -#if !defined M_SQRT2 - #define M_SQRT2 1.414213562373095048801688724209698079 -#endif - -#if !defined M_LN2 - #define M_LN2 0.693147180559945309417232121458176568 -#endif - -#endif diff --git a/C/src/soxr-0.1.3/src/pffft-avx.h b/C/src/soxr-0.1.3/src/pffft-avx.h deleted file mode 100644 index ace19b57..00000000 --- a/C/src/soxr-0.1.3/src/pffft-avx.h +++ /dev/null @@ -1,40 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -/* AVX support macros */ - -#if !defined soxr_avx_included -#define soxr_avx_included - -#include - -typedef __m256d v4sf; -#define VZERO() _mm256_setzero_pd() -#define VMUL(a,b) _mm256_mul_pd(a,b) -#define VADD(a,b) _mm256_add_pd(a,b) -#define VMADD(a,b,c) VADD(VMUL(a,b),c) /* Note: gcc -mfma will `fuse' these */ -#define VSUB(a,b) _mm256_sub_pd(a,b) -#define LD_PS1(p) _mm256_set1_pd(p) -#define INTERLEAVE2(in1, in2, out1, out2) {v4sf \ - t1 = _mm256_unpacklo_pd(in1, in2), \ - t2 = _mm256_unpackhi_pd(in1, in2); \ - out1 = _mm256_permute2f128_pd(t1,t2,0x20); \ - out2 = _mm256_permute2f128_pd(t1,t2,0x31); } -#define UNINTERLEAVE2(in1, in2, out1, out2) {v4sf \ - t1 = _mm256_permute2f128_pd(in1,in2,0x20), \ - t2 = _mm256_permute2f128_pd(in1,in2,0x31); \ - out1 = _mm256_unpacklo_pd(t1, t2); \ - out2 = _mm256_unpackhi_pd(t1, t2);} -#define VTRANSPOSE4(x0,x1,x2,x3) {v4sf \ - t0 = _mm256_shuffle_pd(x0,x1, 0x0), \ - t2 = _mm256_shuffle_pd(x0,x1, 0xf), \ - t1 = _mm256_shuffle_pd(x2,x3, 0x0), \ - t3 = _mm256_shuffle_pd(x2,x3, 0xf); \ - x0 = _mm256_permute2f128_pd(t0,t1, 0x20); \ - x1 = _mm256_permute2f128_pd(t2,t3, 0x20); \ - x2 = _mm256_permute2f128_pd(t0,t1, 0x31); \ - x3 = _mm256_permute2f128_pd(t2,t3, 0x31);} -#define VSWAPHL(a,b) _mm256_permute2f128_pd(b, a, 0x30) -#define VALIGNED(ptr) ((((long)(ptr)) & 0x1F) == 0) - -#endif diff --git a/C/src/soxr-0.1.3/src/pffft-wrap.c b/C/src/soxr-0.1.3/src/pffft-wrap.c deleted file mode 100644 index c920f06e..00000000 --- a/C/src/soxr-0.1.3/src/pffft-wrap.c +++ /dev/null @@ -1,110 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#if !defined PFFT_MACROS_ONLY - -#include "math-wrap.h" - -#if PFFFT_DOUBLE - #include "util64s.h" -#else - #include "util32s.h" - #define sin(x) sinf(x) - #define cos(x) cosf(x) -#endif - -#define pffft_aligned_free SIMD_ALIGNED_FREE -#define pffft_aligned_malloc SIMD_ALIGNED_MALLOC -#define pffft_aligned_calloc SIMD_ALIGNED_CALLOC - -#undef inline -#define inline __inline - -#endif - - - -#include "pffft.c" - - - -#if !defined PFFT_MACROS_ONLY - -#if !defined PFFFT_SIMD_DISABLE - -static void pffft_zconvolve(PFFFT_Setup *s, const float *a, const float *b, float *ab) { - int i, Ncvec = s->Ncvec; - const v4sf * /*RESTRICT*/ va = (const v4sf*)a; - const v4sf * RESTRICT vb = (const v4sf*)b; - v4sf * /*RESTRICT*/ vab = (v4sf*)ab; - - float ar, ai, br, bi; - -#ifdef __arm__ - __builtin_prefetch(va); - __builtin_prefetch(vb); - __builtin_prefetch(va+2); - __builtin_prefetch(vb+2); - __builtin_prefetch(va+4); - __builtin_prefetch(vb+4); - __builtin_prefetch(va+6); - __builtin_prefetch(vb+6); -#endif - - assert(VALIGNED(a) && VALIGNED(b) && VALIGNED(ab)); - ar = ((v4sf_union*)va)[0].f[0]; - ai = ((v4sf_union*)va)[1].f[0]; - br = ((v4sf_union*)vb)[0].f[0]; - bi = ((v4sf_union*)vb)[1].f[0]; - - for (i=0; i < Ncvec; i += 2) { - v4sf ar, ai, br, bi; - ar = va[2*i+0]; ai = va[2*i+1]; - br = vb[2*i+0]; bi = vb[2*i+1]; - VCPLXMUL(ar, ai, br, bi); - vab[2*i+0] = ar; - vab[2*i+1] = ai; - ar = va[2*i+2]; ai = va[2*i+3]; - br = vb[2*i+2]; bi = vb[2*i+3]; - VCPLXMUL(ar, ai, br, bi); - vab[2*i+2] = ar; - vab[2*i+3] = ai; - } - if (s->transform == PFFFT_REAL) { - ((v4sf_union*)vab)[0].f[0] = ar*br; - ((v4sf_union*)vab)[1].f[0] = ai*bi; - } -} - -#else - -static void pffft_zconvolve(PFFFT_Setup *s, const float *a, const float *b, float *ab) { - int i, Ncvec = s->Ncvec; - - if (s->transform == PFFFT_REAL) { - /* take care of the fftpack ordering */ - ab[0] = a[0]*b[0]; - ab[2*Ncvec-1] = a[2*Ncvec-1]*b[2*Ncvec-1]; - ++ab; ++a; ++b; --Ncvec; - } - for (i=0; i < Ncvec; ++i) { - float ar, ai, br, bi; - ar = a[2*i+0]; ai = a[2*i+1]; - br = b[2*i+0]; bi = b[2*i+1]; - VCPLXMUL(ar, ai, br, bi); - ab[2*i+0] = ar; - ab[2*i+1] = ai; - } -} - -#endif - -#include - -static void pffft_reorder_back(int length, void * setup, float * data, float * work) -{ - memcpy(work, data, (unsigned)length * sizeof(*work)); - pffft_zreorder(setup, work, data, PFFFT_BACKWARD); -} - -#endif diff --git a/C/src/soxr-0.1.3/src/pffft.c b/C/src/soxr-0.1.3/src/pffft.c deleted file mode 100644 index 46c841e7..00000000 --- a/C/src/soxr-0.1.3/src/pffft.c +++ /dev/null @@ -1,1946 +0,0 @@ -/* https://bitbucket.org/jpommier/pffft/raw/483453d8f7661058e74aa4e7cf5c27bcd7887e7a/pffft.c - * with minor changes for libsoxr. */ - -/* Copyright (c) 2013 Julien Pommier ( pommier@modartt.com ) - - Based on original fortran 77 code from FFTPACKv4 from NETLIB - (http://www.netlib.org/fftpack), authored by Dr Paul Swarztrauber - of NCAR, in 1985. - - As confirmed by the NCAR fftpack software curators, the following - FFTPACKv5 license applies to FFTPACKv4 sources. My changes are - released under the same terms. - - FFTPACK license: - - http://www.cisl.ucar.edu/css/software/fftpack5/ftpk.html - - Copyright (c) 2004 the University Corporation for Atmospheric - Research ("UCAR"). All rights reserved. Developed by NCAR's - Computational and Information Systems Laboratory, UCAR, - www.cisl.ucar.edu. - - Redistribution and use of the Software in source and binary forms, - with or without modification, is permitted provided that the - following conditions are met: - - - Neither the names of NCAR's Computational and Information Systems - Laboratory, the University Corporation for Atmospheric Research, - nor the names of its sponsors or contributors may be used to - endorse or promote products derived from this Software without - specific prior written permission. - - - Redistributions of source code must retain the above copyright - notices, this list of conditions, and the disclaimer below. - - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions, and the disclaimer below in the - documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES OR OTHER LIABILITY, WHETHER IN AN - ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE - SOFTWARE. - - - PFFFT : a Pretty Fast FFT. - - This file is largerly based on the original FFTPACK implementation, modified in - order to take advantage of SIMD instructions of modern CPUs. -*/ - -/* - ChangeLog: - - 2011/10/02, version 1: This is the very first release of this file. -*/ - -#include "pffft.h" -#include -#include -#include -#include - -/* detect compiler flavour */ -#if defined(_MSC_VER) -# define COMPILER_MSVC -#elif defined(__GNUC__) -# define COMPILER_GCC -#endif - -#if defined(COMPILER_GCC) -# define ALWAYS_INLINE(return_type) inline return_type __attribute__ ((always_inline)) -# define NEVER_INLINE(return_type) return_type __attribute__ ((noinline)) -# define RESTRICT __restrict -# define VLA_ARRAY_ON_STACK(type__, varname__, size__) type__ varname__[size__]; -#elif defined(COMPILER_MSVC) -# define ALWAYS_INLINE(return_type) __forceinline return_type -# define NEVER_INLINE(return_type) __declspec(noinline) return_type -# define RESTRICT __restrict -# define VLA_ARRAY_ON_STACK(type__, varname__, size__) type__ *varname__ = (type__*)_alloca(size__ * sizeof(type__)) -#endif - - -/* - vector support macros: the rest of the code is independant of - SSE/Altivec/NEON -- adding support for other platforms with 4-element - vectors should be limited to these macros -*/ - - -/* define PFFFT_SIMD_DISABLE if you want to use scalar code instead of simd code */ -/*#define PFFFT_SIMD_DISABLE */ - -/* - Altivec support macros -*/ -#if !defined(PFFFT_SIMD_DISABLE) && (defined(__ppc__) || defined(__ppc64__)) -typedef vector float v4sf; -# define SIMD_SZ 4 -# define VZERO() ((vector float) vec_splat_u8(0)) -# define VMUL(a,b) vec_madd(a,b, VZERO()) -# define VADD(a,b) vec_add(a,b) -# define VMADD(a,b,c) vec_madd(a,b,c) -# define VSUB(a,b) vec_sub(a,b) -inline v4sf ld_ps1(const float *p) { v4sf v=vec_lde(0,p); return vec_splat(vec_perm(v, v, vec_lvsl(0, p)), 0); } -# define LD_PS1(p) ld_ps1(&p) -# define INTERLEAVE2(in1, in2, out1, out2) { v4sf tmp__ = vec_mergeh(in1, in2); out2 = vec_mergel(in1, in2); out1 = tmp__; } -# define UNINTERLEAVE2(in1, in2, out1, out2) { \ - vector unsigned char vperm1 = (vector unsigned char)(0,1,2,3,8,9,10,11,16,17,18,19,24,25,26,27); \ - vector unsigned char vperm2 = (vector unsigned char)(4,5,6,7,12,13,14,15,20,21,22,23,28,29,30,31); \ - v4sf tmp__ = vec_perm(in1, in2, vperm1); out2 = vec_perm(in1, in2, vperm2); out1 = tmp__; \ - } -# define VTRANSPOSE4(x0,x1,x2,x3) { \ - v4sf y0 = vec_mergeh(x0, x2); \ - v4sf y1 = vec_mergel(x0, x2); \ - v4sf y2 = vec_mergeh(x1, x3); \ - v4sf y3 = vec_mergel(x1, x3); \ - x0 = vec_mergeh(y0, y2); \ - x1 = vec_mergel(y0, y2); \ - x2 = vec_mergeh(y1, y3); \ - x3 = vec_mergel(y1, y3); \ - } -# define VSWAPHL(a,b) vec_perm(a,b, (vector unsigned char)(16,17,18,19,20,21,22,23,8,9,10,11,12,13,14,15)) -# define VALIGNED(ptr) ((((long)(ptr)) & 0xF) == 0) - -/* - SSE1 support macros -*/ -#elif !defined(PFFFT_SIMD_DISABLE) && (defined(__x86_64__) || defined(_M_X64) || defined(i386) || defined(_M_IX86)) - -# define SIMD_SZ 4 /* 4 floats by simd vector -- this is pretty much hardcoded in the preprocess/finalize functions anyway so you will have to work if you want to enable AVX with its 256-bit vectors. */ - -#if !PFFFT_DOUBLE -#include -typedef __m128 v4sf; -# define VZERO() _mm_setzero_ps() -# define VMUL(a,b) _mm_mul_ps(a,b) -# define VADD(a,b) _mm_add_ps(a,b) -# define VMADD(a,b,c) _mm_add_ps(_mm_mul_ps(a,b), c) -# define VSUB(a,b) _mm_sub_ps(a,b) -# define LD_PS1(p) _mm_set1_ps(p) -# define INTERLEAVE2(in1, in2, out1, out2) { v4sf tmp__ = _mm_unpacklo_ps(in1, in2); out2 = _mm_unpackhi_ps(in1, in2); out1 = tmp__; } -# define UNINTERLEAVE2(in1, in2, out1, out2) { v4sf tmp__ = _mm_shuffle_ps(in1, in2, _MM_SHUFFLE(2,0,2,0)); out2 = _mm_shuffle_ps(in1, in2, _MM_SHUFFLE(3,1,3,1)); out1 = tmp__; } -# define VTRANSPOSE4(x0,x1,x2,x3) _MM_TRANSPOSE4_PS(x0,x1,x2,x3) -# define VSWAPHL(a,b) _mm_shuffle_ps(b, a, _MM_SHUFFLE(3,2,1,0)) -# define VALIGNED(ptr) ((((long)(ptr)) & 0xF) == 0) - -#else -#include "pffft-avx.h" -#endif - -/* - ARM NEON support macros -*/ -#elif !defined(PFFFT_SIMD_DISABLE) && defined(__arm__) -# include -typedef float32x4_t v4sf; -# define SIMD_SZ 4 -# define VZERO() vdupq_n_f32(0) -# define VMUL(a,b) vmulq_f32(a,b) -# define VADD(a,b) vaddq_f32(a,b) -# define VMADD(a,b,c) vmlaq_f32(c,a,b) -# define VSUB(a,b) vsubq_f32(a,b) -# define LD_PS1(p) vld1q_dup_f32(&(p)) -# define INTERLEAVE2(in1, in2, out1, out2) { float32x4x2_t tmp__ = vzipq_f32(in1,in2); out1=tmp__.val[0]; out2=tmp__.val[1]; } -# define UNINTERLEAVE2(in1, in2, out1, out2) { float32x4x2_t tmp__ = vuzpq_f32(in1,in2); out1=tmp__.val[0]; out2=tmp__.val[1]; } -# define VTRANSPOSE4(x0,x1,x2,x3) { \ - float32x4x2_t t0_ = vzipq_f32(x0, x2); \ - float32x4x2_t t1_ = vzipq_f32(x1, x3); \ - float32x4x2_t u0_ = vzipq_f32(t0_.val[0], t1_.val[0]); \ - float32x4x2_t u1_ = vzipq_f32(t0_.val[1], t1_.val[1]); \ - x0 = u0_.val[0]; x1 = u0_.val[1]; x2 = u1_.val[0]; x3 = u1_.val[1]; \ - } -/* marginally faster version */ -/*# define VTRANSPOSE4(x0,x1,x2,x3) { asm("vtrn.32 %q0, %q1;\n vtrn.32 %q2,%q3\n vswp %f0,%e2\n vswp %f1,%e3" : "+w"(x0), "+w"(x1), "+w"(x2), "+w"(x3)::); } */ -# define VSWAPHL(a,b) vcombine_f32(vget_low_f32(b), vget_high_f32(a)) -# define VALIGNED(ptr) ((((long)(ptr)) & 0x3) == 0) -#else -# if !defined(PFFFT_SIMD_DISABLE) -# warning "building with simd disabled !\n"; -# define PFFFT_SIMD_DISABLE /* fallback to scalar code */ -# endif -#endif - -#if PFFFT_DOUBLE -#define float double -#endif - -/* fallback mode for situations where SSE/Altivec are not available, use scalar mode instead */ -#ifdef PFFFT_SIMD_DISABLE -typedef float v4sf; -# define SIMD_SZ 1 -# define VZERO() 0.f -# define VMUL(a,b) ((a)*(b)) -# define VADD(a,b) ((a)+(b)) -# define VMADD(a,b,c) ((a)*(b)+(c)) -# define VSUB(a,b) ((a)-(b)) -# define LD_PS1(p) (p) -# define VALIGNED(ptr) ((((long)(ptr)) & 0x3) == 0) -#endif - -/* shortcuts for complex multiplcations */ -#define VCPLXMUL(ar,ai,br,bi) { v4sf tmp; tmp=VMUL(ar,bi); ar=VMUL(ar,br); ar=VSUB(ar,VMUL(ai,bi)); ai=VMUL(ai,br); ai=VADD(ai,tmp); } -#define VCPLXMULCONJ(ar,ai,br,bi) { v4sf tmp; tmp=VMUL(ar,bi); ar=VMUL(ar,br); ar=VADD(ar,VMUL(ai,bi)); ai=VMUL(ai,br); ai=VSUB(ai,tmp); } -#ifndef SVMUL -/* multiply a scalar with a vector */ -#define SVMUL(f,v) VMUL(LD_PS1(f),v) -#endif - -#if !defined PFFT_MACROS_ONLY - -#if !defined(PFFFT_SIMD_DISABLE) -typedef union v4sf_union { - v4sf v; - float f[4]; -} v4sf_union; - -#if 0 -#include - -#define assertv4(v,f0,f1,f2,f3) assert(v.f[0] == (f0) && v.f[1] == (f1) && v.f[2] == (f2) && v.f[3] == (f3)) - -/* detect bugs with the vector support macros */ -void validate_pffft_simd(void); -void validate_pffft_simd(void) { - float f[16] = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }; - v4sf_union a0, a1, a2, a3, t, u; - memcpy(a0.f, f, 4*sizeof(float)); - memcpy(a1.f, f+4, 4*sizeof(float)); - memcpy(a2.f, f+8, 4*sizeof(float)); - memcpy(a3.f, f+12, 4*sizeof(float)); - - t = a0; u = a1; t.v = VZERO(); - printf("VZERO=[%2g %2g %2g %2g]\n", t.f[0], t.f[1], t.f[2], t.f[3]); assertv4(t, 0, 0, 0, 0); - t.v = VADD(a1.v, a2.v); - printf("VADD(4:7,8:11)=[%2g %2g %2g %2g]\n", t.f[0], t.f[1], t.f[2], t.f[3]); assertv4(t, 12, 14, 16, 18); - t.v = VMUL(a1.v, a2.v); - printf("VMUL(4:7,8:11)=[%2g %2g %2g %2g]\n", t.f[0], t.f[1], t.f[2], t.f[3]); assertv4(t, 32, 45, 60, 77); - t.v = VMADD(a1.v, a2.v,a0.v); - printf("VMADD(4:7,8:11,0:3)=[%2g %2g %2g %2g]\n", t.f[0], t.f[1], t.f[2], t.f[3]); assertv4(t, 32, 46, 62, 80); - INTERLEAVE2(a1.v,a2.v,t.v,u.v); - printf("INTERLEAVE2(4:7,8:11)=[%2g %2g %2g %2g] [%2g %2g %2g %2g]\n", t.f[0], t.f[1], t.f[2], t.f[3], u.f[0], u.f[1], u.f[2], u.f[3]); - assertv4(t, 4, 8, 5, 9); assertv4(u, 6, 10, 7, 11); - UNINTERLEAVE2(a1.v,a2.v,t.v,u.v); - printf("UNINTERLEAVE2(4:7,8:11)=[%2g %2g %2g %2g] [%2g %2g %2g %2g]\n", t.f[0], t.f[1], t.f[2], t.f[3], u.f[0], u.f[1], u.f[2], u.f[3]); - assertv4(t, 4, 6, 8, 10); assertv4(u, 5, 7, 9, 11); - - t.v=LD_PS1(f[15]); - printf("LD_PS1(15)=[%2g %2g %2g %2g]\n", t.f[0], t.f[1], t.f[2], t.f[3]); - assertv4(t, 15, 15, 15, 15); - t.v = VSWAPHL(a1.v, a2.v); - printf("VSWAPHL(4:7,8:11)=[%2g %2g %2g %2g]\n", t.f[0], t.f[1], t.f[2], t.f[3]); - assertv4(t, 8, 9, 6, 7); - VTRANSPOSE4(a0.v, a1.v, a2.v, a3.v); - printf("VTRANSPOSE4(0:3,4:7,8:11,12:15)=[%2g %2g %2g %2g] [%2g %2g %2g %2g] [%2g %2g %2g %2g] [%2g %2g %2g %2g]\n", - a0.f[0], a0.f[1], a0.f[2], a0.f[3], a1.f[0], a1.f[1], a1.f[2], a1.f[3], - a2.f[0], a2.f[1], a2.f[2], a2.f[3], a3.f[0], a3.f[1], a3.f[2], a3.f[3]); - assertv4(a0, 0, 4, 8, 12); assertv4(a1, 1, 5, 9, 13); assertv4(a2, 2, 6, 10, 14); assertv4(a3, 3, 7, 11, 15); -} -#endif -#endif /*!PFFFT_SIMD_DISABLE */ - -#if 0 -/* SSE and co like 16-bytes aligned pointers */ -#define MALLOC_V4SF_ALIGNMENT 64 /* with a 64-byte alignment, we are even aligned on L2 cache lines... */ -void *pffft_aligned_malloc(size_t nb_bytes) { - void *p, *p0 = malloc(nb_bytes + MALLOC_V4SF_ALIGNMENT); - if (!p0) return (void *) 0; - p = (void *) (((size_t) p0 + MALLOC_V4SF_ALIGNMENT) & (~((size_t) (MALLOC_V4SF_ALIGNMENT-1)))); - *((void **) p - 1) = p0; - return p; -} - -void pffft_aligned_free(void *p) { - if (p) free(*((void **) p - 1)); -} - -int pffft_simd_size() { return SIMD_SZ; } -#endif - -/* - passf2 and passb2 has been merged here, fsign = -1 for passf2, +1 for passb2 -*/ -static NEVER_INLINE(void) passf2_ps(int ido, int l1, const v4sf *cc, v4sf *ch, const float *wa1, float fsign) { - int k, i; - int l1ido = l1*ido; - if (ido <= 2) { - for (k=0; k < l1ido; k += ido, ch += ido, cc+= 2*ido) { - ch[0] = VADD(cc[0], cc[ido+0]); - ch[l1ido] = VSUB(cc[0], cc[ido+0]); - ch[1] = VADD(cc[1], cc[ido+1]); - ch[l1ido + 1] = VSUB(cc[1], cc[ido+1]); - } - } else { - for (k=0; k < l1ido; k += ido, ch += ido, cc += 2*ido) { - for (i=0; i 2); - for (k=0; k< l1ido; k += ido, cc+= 3*ido, ch +=ido) { - for (i=0; i 2); - for (k = 0; k < l1; ++k, cc += 5*ido, ch += ido) { - for (i = 0; i < ido-1; i += 2) { - ti5 = VSUB(cc_ref(i , 2), cc_ref(i , 5)); - ti2 = VADD(cc_ref(i , 2), cc_ref(i , 5)); - ti4 = VSUB(cc_ref(i , 3), cc_ref(i , 4)); - ti3 = VADD(cc_ref(i , 3), cc_ref(i , 4)); - tr5 = VSUB(cc_ref(i-1, 2), cc_ref(i-1, 5)); - tr2 = VADD(cc_ref(i-1, 2), cc_ref(i-1, 5)); - tr4 = VSUB(cc_ref(i-1, 3), cc_ref(i-1, 4)); - tr3 = VADD(cc_ref(i-1, 3), cc_ref(i-1, 4)); - ch_ref(i-1, 1) = VADD(cc_ref(i-1, 1), VADD(tr2, tr3)); - ch_ref(i , 1) = VADD(cc_ref(i , 1), VADD(ti2, ti3)); - cr2 = VADD(cc_ref(i-1, 1), VADD(SVMUL(tr11, tr2),SVMUL(tr12, tr3))); - ci2 = VADD(cc_ref(i , 1), VADD(SVMUL(tr11, ti2),SVMUL(tr12, ti3))); - cr3 = VADD(cc_ref(i-1, 1), VADD(SVMUL(tr12, tr2),SVMUL(tr11, tr3))); - ci3 = VADD(cc_ref(i , 1), VADD(SVMUL(tr12, ti2),SVMUL(tr11, ti3))); - cr5 = VADD(SVMUL(ti11, tr5), SVMUL(ti12, tr4)); - ci5 = VADD(SVMUL(ti11, ti5), SVMUL(ti12, ti4)); - cr4 = VSUB(SVMUL(ti12, tr5), SVMUL(ti11, tr4)); - ci4 = VSUB(SVMUL(ti12, ti5), SVMUL(ti11, ti4)); - dr3 = VSUB(cr3, ci4); - dr4 = VADD(cr3, ci4); - di3 = VADD(ci3, cr4); - di4 = VSUB(ci3, cr4); - dr5 = VADD(cr2, ci5); - dr2 = VSUB(cr2, ci5); - di5 = VSUB(ci2, cr5); - di2 = VADD(ci2, cr5); - wr1=wa1[i], wi1=fsign*wa1[i+1], wr2=wa2[i], wi2=fsign*wa2[i+1]; - wr3=wa3[i], wi3=fsign*wa3[i+1], wr4=wa4[i], wi4=fsign*wa4[i+1]; - VCPLXMUL(dr2, di2, LD_PS1(wr1), LD_PS1(wi1)); - ch_ref(i - 1, 2) = dr2; - ch_ref(i, 2) = di2; - VCPLXMUL(dr3, di3, LD_PS1(wr2), LD_PS1(wi2)); - ch_ref(i - 1, 3) = dr3; - ch_ref(i, 3) = di3; - VCPLXMUL(dr4, di4, LD_PS1(wr3), LD_PS1(wi3)); - ch_ref(i - 1, 4) = dr4; - ch_ref(i, 4) = di4; - VCPLXMUL(dr5, di5, LD_PS1(wr4), LD_PS1(wi4)); - ch_ref(i - 1, 5) = dr5; - ch_ref(i, 5) = di5; - } - } -#undef ch_ref -#undef cc_ref -} -#endif - -static NEVER_INLINE(void) radf2_ps(int ido, int l1, const v4sf * RESTRICT cc, v4sf * RESTRICT ch, const float *wa1) { - static const float minus_one = -1.f; - int i, k, l1ido = l1*ido; - for (k=0; k < l1ido; k += ido) { - v4sf a = cc[k], b = cc[k + l1ido]; - ch[2*k] = VADD(a, b); - ch[2*(k+ido)-1] = VSUB(a, b); - } - if (ido < 2) return; - if (ido != 2) { - for (k=0; k < l1ido; k += ido) { - for (i=2; i 5) { - wa[i1-1] = wa[i-1]; - wa[i1] = wa[i]; - } - } - l1 = l2; - } -} /* cffti1 */ - - -static -v4sf *cfftf1_ps(int n, const v4sf *input_readonly, v4sf *work1, v4sf *work2, const float *wa, const int *ifac, int isign) { - v4sf *in = (v4sf*)input_readonly; - v4sf *out = (in == work2 ? work1 : work2); - int nf = ifac[1], k1; - int l1 = 1; - int iw = 0; - assert(in != out && work1 != work2); - for (k1=2; k1<=nf+1; k1++) { - int ip = ifac[k1]; - int l2 = ip*l1; - int ido = n / l2; - int idot = ido + ido; - switch (ip) { -#if 0 - case 5: { - int ix2 = iw + idot; - int ix3 = ix2 + idot; - int ix4 = ix3 + idot; - passf5_ps(idot, l1, in, out, &wa[iw], &wa[ix2], &wa[ix3], &wa[ix4], (float)isign); - } break; -#endif - case 4: { - int ix2 = iw + idot; - int ix3 = ix2 + idot; - passf4_ps(idot, l1, in, out, &wa[iw], &wa[ix2], &wa[ix3], (float)isign); - } break; - case 2: { - passf2_ps(idot, l1, in, out, &wa[iw], (float)isign); - } break; -#if 0 - case 3: { - int ix2 = iw + idot; - passf3_ps(idot, l1, in, out, &wa[iw], &wa[ix2], (float)isign); - } break; -#endif - default: - assert(0); - } - l1 = l2; - iw += (ip - 1)*idot; - if (out == work2) { - out = work1; in = work2; - } else { - out = work2; in = work1; - } - } - - return in; /* this is in fact the output .. */ -} - - -struct PFFFT_Setup { - int N; - int Ncvec; /* nb of complex simd vectors (N/4 if PFFFT_COMPLEX, N/8 if PFFFT_REAL) */ - int ifac[15]; - pffft_transform_t transform; - v4sf *data; /* allocated room for twiddle coefs */ - float *e; /* points into 'data' , N/4*3 elements */ - float *twiddle; /* points into 'data', N/4 elements */ -}; - -static -PFFFT_Setup *pffft_new_setup(int N, pffft_transform_t transform) { - PFFFT_Setup *s = (PFFFT_Setup*)malloc(sizeof(PFFFT_Setup)); - int k, m; - if (!s) return s; - /* unfortunately, the fft size must be a multiple of 16 for complex FFTs - and 32 for real FFTs -- a lot of stuff would need to be rewritten to - handle other cases (or maybe just switch to a scalar fft, I don't know..) */ - if (transform == PFFFT_REAL) { assert((N%(2*SIMD_SZ*SIMD_SZ))==0 && N>0); } - if (transform == PFFFT_COMPLEX) { assert((N%(SIMD_SZ*SIMD_SZ))==0 && N>0); } - /*assert((N % 32) == 0); */ - s->N = N; - s->transform = transform; - /* nb of complex simd vectors */ - s->Ncvec = (transform == PFFFT_REAL ? N/2 : N)/SIMD_SZ; - s->data = (v4sf*)pffft_aligned_malloc(2*(size_t)s->Ncvec * sizeof(v4sf)); - if (!s->data) {free(s); return 0;} - s->e = (float*)s->data; - s->twiddle = (float*)(s->data + (2*s->Ncvec*(SIMD_SZ-1))/SIMD_SZ); - - if (transform == PFFFT_REAL) { - for (k=0; k < s->Ncvec; ++k) { - int i = k/SIMD_SZ; - int j = k%SIMD_SZ; - for (m=0; m < SIMD_SZ-1; ++m) { - float A = (float)(-2*M_PI*(m+1)*k / N); - s->e[(2*(i*3 + m) + 0) * SIMD_SZ + j] = cos(A); - s->e[(2*(i*3 + m) + 1) * SIMD_SZ + j] = sin(A); - } - } - rffti1_ps(N/SIMD_SZ, s->twiddle, s->ifac); - } else { - for (k=0; k < s->Ncvec; ++k) { - int i = k/SIMD_SZ; - int j = k%SIMD_SZ; - for (m=0; m < SIMD_SZ-1; ++m) { - float A = (float)(-2*M_PI*(m+1)*k / N); - s->e[(2*(i*3 + m) + 0)*SIMD_SZ + j] = cos(A); - s->e[(2*(i*3 + m) + 1)*SIMD_SZ + j] = sin(A); - } - } - cffti1_ps(N/SIMD_SZ, s->twiddle, s->ifac); - } - - /* check that N is decomposable with allowed prime factors */ - for (k=0, m=1; k < s->ifac[1]; ++k) { m *= s->ifac[2+k]; } - if (m != N/SIMD_SZ) { - pffft_destroy_setup(s); s = 0; - } - - return s; -} - - -static -void pffft_destroy_setup(PFFFT_Setup *s) { - if (!s) return; - pffft_aligned_free(s->data); - free(s); -} - -#if !defined(PFFFT_SIMD_DISABLE) - -/* [0 0 1 2 3 4 5 6 7 8] -> [0 8 7 6 5 4 3 2 1] */ -static void reversed_copy(int N, const v4sf *in, int in_stride, v4sf *out) { - v4sf g0, g1; - int k; - INTERLEAVE2(in[0], in[1], g0, g1); in += in_stride; - - *--out = VSWAPHL(g0, g1); /* [g0l, g0h], [g1l g1h] -> [g1l, g0h] */ - for (k=1; k < N; ++k) { - v4sf h0, h1; - INTERLEAVE2(in[0], in[1], h0, h1); in += in_stride; - *--out = VSWAPHL(g1, h0); - *--out = VSWAPHL(h0, h1); - g1 = h1; - } - *--out = VSWAPHL(g1, g0); -} - -static void unreversed_copy(int N, const v4sf *in, v4sf *out, int out_stride) { - v4sf g0, g1, h0, h1; - int k; - g0 = g1 = in[0]; ++in; - for (k=1; k < N; ++k) { - h0 = *in++; h1 = *in++; - g1 = VSWAPHL(g1, h0); - h0 = VSWAPHL(h0, h1); - UNINTERLEAVE2(h0, g1, out[0], out[1]); out += out_stride; - g1 = h1; - } - h0 = *in++; h1 = g0; - g1 = VSWAPHL(g1, h0); - h0 = VSWAPHL(h0, h1); - UNINTERLEAVE2(h0, g1, out[0], out[1]); -} - -static -void pffft_zreorder(PFFFT_Setup *setup, const float *in, float *out, pffft_direction_t direction) { - int k, N = setup->N, Ncvec = setup->Ncvec; - const v4sf *vin = (const v4sf*)in; - v4sf *vout = (v4sf*)out; - assert(in != out); - if (setup->transform == PFFFT_REAL) { - int k, dk = N/32; - if (direction == PFFFT_FORWARD) { - for (k=0; k < dk; ++k) { - INTERLEAVE2(vin[k*8 + 0], vin[k*8 + 1], vout[2*(0*dk + k) + 0], vout[2*(0*dk + k) + 1]); - INTERLEAVE2(vin[k*8 + 4], vin[k*8 + 5], vout[2*(2*dk + k) + 0], vout[2*(2*dk + k) + 1]); - } - reversed_copy(dk, vin+2, 8, (v4sf*)(out + N/2)); - reversed_copy(dk, vin+6, 8, (v4sf*)(out + N)); - } else { - for (k=0; k < dk; ++k) { - UNINTERLEAVE2(vin[2*(0*dk + k) + 0], vin[2*(0*dk + k) + 1], vout[k*8 + 0], vout[k*8 + 1]); - UNINTERLEAVE2(vin[2*(2*dk + k) + 0], vin[2*(2*dk + k) + 1], vout[k*8 + 4], vout[k*8 + 5]); - } - unreversed_copy(dk, (v4sf*)(in + N/4), (v4sf*)(out + N - 6*SIMD_SZ), -8); - unreversed_copy(dk, (v4sf*)(in + 3*N/4), (v4sf*)(out + N - 2*SIMD_SZ), -8); - } - } else { - if (direction == PFFFT_FORWARD) { - for (k=0; k < Ncvec; ++k) { - int kk = (k/4) + (k%4)*(Ncvec/4); - INTERLEAVE2(vin[k*2], vin[k*2+1], vout[kk*2], vout[kk*2+1]); - } - } else { - for (k=0; k < Ncvec; ++k) { - int kk = (k/4) + (k%4)*(Ncvec/4); - UNINTERLEAVE2(vin[kk*2], vin[kk*2+1], vout[k*2], vout[k*2+1]); - } - } - } -} - -static -void pffft_cplx_finalize(int Ncvec, const v4sf *in, v4sf *out, const v4sf *e) { - int k, dk = Ncvec/SIMD_SZ; /* number of 4x4 matrix blocks */ - v4sf r0, i0, r1, i1, r2, i2, r3, i3; - v4sf sr0, dr0, sr1, dr1, si0, di0, si1, di1; - assert(in != out); - for (k=0; k < dk; ++k) { - r0 = in[8*k+0]; i0 = in[8*k+1]; - r1 = in[8*k+2]; i1 = in[8*k+3]; - r2 = in[8*k+4]; i2 = in[8*k+5]; - r3 = in[8*k+6]; i3 = in[8*k+7]; - VTRANSPOSE4(r0,r1,r2,r3); - VTRANSPOSE4(i0,i1,i2,i3); - VCPLXMUL(r1,i1,e[k*6+0],e[k*6+1]); - VCPLXMUL(r2,i2,e[k*6+2],e[k*6+3]); - VCPLXMUL(r3,i3,e[k*6+4],e[k*6+5]); - - sr0 = VADD(r0,r2); dr0 = VSUB(r0, r2); - sr1 = VADD(r1,r3); dr1 = VSUB(r1, r3); - si0 = VADD(i0,i2); di0 = VSUB(i0, i2); - si1 = VADD(i1,i3); di1 = VSUB(i1, i3); - - /* - transformation for each column is: - - [1 1 1 1 0 0 0 0] [r0] - [1 0 -1 0 0 -1 0 1] [r1] - [1 -1 1 -1 0 0 0 0] [r2] - [1 0 -1 0 0 1 0 -1] [r3] - [0 0 0 0 1 1 1 1] * [i0] - [0 1 0 -1 1 0 -1 0] [i1] - [0 0 0 0 1 -1 1 -1] [i2] - [0 -1 0 1 1 0 -1 0] [i3] - */ - - r0 = VADD(sr0, sr1); i0 = VADD(si0, si1); - r1 = VADD(dr0, di1); i1 = VSUB(di0, dr1); - r2 = VSUB(sr0, sr1); i2 = VSUB(si0, si1); - r3 = VSUB(dr0, di1); i3 = VADD(di0, dr1); - - *out++ = r0; *out++ = i0; *out++ = r1; *out++ = i1; - *out++ = r2; *out++ = i2; *out++ = r3; *out++ = i3; - } -} - -static -void pffft_cplx_preprocess(int Ncvec, const v4sf *in, v4sf *out, const v4sf *e) { - int k, dk = Ncvec/SIMD_SZ; /* number of 4x4 matrix blocks */ - v4sf r0, i0, r1, i1, r2, i2, r3, i3; - v4sf sr0, dr0, sr1, dr1, si0, di0, si1, di1; - assert(in != out); - for (k=0; k < dk; ++k) { - r0 = in[8*k+0]; i0 = in[8*k+1]; - r1 = in[8*k+2]; i1 = in[8*k+3]; - r2 = in[8*k+4]; i2 = in[8*k+5]; - r3 = in[8*k+6]; i3 = in[8*k+7]; - - sr0 = VADD(r0,r2); dr0 = VSUB(r0, r2); - sr1 = VADD(r1,r3); dr1 = VSUB(r1, r3); - si0 = VADD(i0,i2); di0 = VSUB(i0, i2); - si1 = VADD(i1,i3); di1 = VSUB(i1, i3); - - r0 = VADD(sr0, sr1); i0 = VADD(si0, si1); - r1 = VSUB(dr0, di1); i1 = VADD(di0, dr1); - r2 = VSUB(sr0, sr1); i2 = VSUB(si0, si1); - r3 = VADD(dr0, di1); i3 = VSUB(di0, dr1); - - VCPLXMULCONJ(r1,i1,e[k*6+0],e[k*6+1]); - VCPLXMULCONJ(r2,i2,e[k*6+2],e[k*6+3]); - VCPLXMULCONJ(r3,i3,e[k*6+4],e[k*6+5]); - - VTRANSPOSE4(r0,r1,r2,r3); - VTRANSPOSE4(i0,i1,i2,i3); - - *out++ = r0; *out++ = i0; *out++ = r1; *out++ = i1; - *out++ = r2; *out++ = i2; *out++ = r3; *out++ = i3; - } -} - - -static ALWAYS_INLINE(void) pffft_real_finalize_4x4(const v4sf *in0, const v4sf *in1, const v4sf *in, - const v4sf *e, v4sf *out) { - v4sf r0, i0, r1, i1, r2, i2, r3, i3; - v4sf sr0, dr0, sr1, dr1, si0, di0, si1, di1; - r0 = *in0; i0 = *in1; - r1 = *in++; i1 = *in++; r2 = *in++; i2 = *in++; r3 = *in++; i3 = *in++; - VTRANSPOSE4(r0,r1,r2,r3); - VTRANSPOSE4(i0,i1,i2,i3); - - /* - transformation for each column is: - - [1 1 1 1 0 0 0 0] [r0] - [1 0 -1 0 0 -1 0 1] [r1] - [1 0 -1 0 0 1 0 -1] [r2] - [1 -1 1 -1 0 0 0 0] [r3] - [0 0 0 0 1 1 1 1] * [i0] - [0 -1 0 1 -1 0 1 0] [i1] - [0 -1 0 1 1 0 -1 0] [i2] - [0 0 0 0 -1 1 -1 1] [i3] - */ - - /*cerr << "matrix initial, before e , REAL:\n 1: " << r0 << "\n 1: " << r1 << "\n 1: " << r2 << "\n 1: " << r3 << "\n"; */ - /*cerr << "matrix initial, before e, IMAG :\n 1: " << i0 << "\n 1: " << i1 << "\n 1: " << i2 << "\n 1: " << i3 << "\n"; */ - - VCPLXMUL(r1,i1,e[0],e[1]); - VCPLXMUL(r2,i2,e[2],e[3]); - VCPLXMUL(r3,i3,e[4],e[5]); - - /*cerr << "matrix initial, real part:\n 1: " << r0 << "\n 1: " << r1 << "\n 1: " << r2 << "\n 1: " << r3 << "\n"; */ - /*cerr << "matrix initial, imag part:\n 1: " << i0 << "\n 1: " << i1 << "\n 1: " << i2 << "\n 1: " << i3 << "\n"; */ - - sr0 = VADD(r0,r2); dr0 = VSUB(r0,r2); - sr1 = VADD(r1,r3); dr1 = VSUB(r3,r1); - si0 = VADD(i0,i2); di0 = VSUB(i0,i2); - si1 = VADD(i1,i3); di1 = VSUB(i3,i1); - - r0 = VADD(sr0, sr1); - r3 = VSUB(sr0, sr1); - i0 = VADD(si0, si1); - i3 = VSUB(si1, si0); - r1 = VADD(dr0, di1); - r2 = VSUB(dr0, di1); - i1 = VSUB(dr1, di0); - i2 = VADD(dr1, di0); - - *out++ = r0; - *out++ = i0; - *out++ = r1; - *out++ = i1; - *out++ = r2; - *out++ = i2; - *out++ = r3; - *out++ = i3; - -} - -static NEVER_INLINE(void) pffft_real_finalize(int Ncvec, const v4sf *in, v4sf *out, const v4sf *e) { - int k, dk = Ncvec/SIMD_SZ; /* number of 4x4 matrix blocks */ - /* fftpack order is f0r f1r f1i f2r f2i ... f(n-1)r f(n-1)i f(n)r */ - - v4sf_union cr, ci, *uout = (v4sf_union*)out; - v4sf save = in[7], zero=VZERO(); - float xr0, xi0, xr1, xi1, xr2, xi2, xr3, xi3; - static const float s = (float)(M_SQRT2/2); - - cr.v = in[0]; ci.v = in[Ncvec*2-1]; - assert(in != out); - pffft_real_finalize_4x4(&zero, &zero, in+1, e, out); - - /* - [cr0 cr1 cr2 cr3 ci0 ci1 ci2 ci3] - - [Xr(1)] ] [1 1 1 1 0 0 0 0] - [Xr(N/4) ] [0 0 0 0 1 s 0 -s] - [Xr(N/2) ] [1 0 -1 0 0 0 0 0] - [Xr(3N/4)] [0 0 0 0 1 -s 0 s] - [Xi(1) ] [1 -1 1 -1 0 0 0 0] - [Xi(N/4) ] [0 0 0 0 0 -s -1 -s] - [Xi(N/2) ] [0 -1 0 1 0 0 0 0] - [Xi(3N/4)] [0 0 0 0 0 -s 1 -s] - */ - - xr0=(cr.f[0]+cr.f[2]) + (cr.f[1]+cr.f[3]); uout[0].f[0] = xr0; - xi0=(cr.f[0]+cr.f[2]) - (cr.f[1]+cr.f[3]); uout[1].f[0] = xi0; - xr2=(cr.f[0]-cr.f[2]); uout[4].f[0] = xr2; - xi2=(cr.f[3]-cr.f[1]); uout[5].f[0] = xi2; - xr1= ci.f[0] + s*(ci.f[1]-ci.f[3]); uout[2].f[0] = xr1; - xi1=-ci.f[2] - s*(ci.f[1]+ci.f[3]); uout[3].f[0] = xi1; - xr3= ci.f[0] - s*(ci.f[1]-ci.f[3]); uout[6].f[0] = xr3; - xi3= ci.f[2] - s*(ci.f[1]+ci.f[3]); uout[7].f[0] = xi3; - - for (k=1; k < dk; ++k) { - v4sf save_next = in[8*k+7]; - pffft_real_finalize_4x4(&save, &in[8*k+0], in + 8*k+1, - e + k*6, out + k*8); - save = save_next; - } - -} - -static ALWAYS_INLINE(void) pffft_real_preprocess_4x4(const v4sf *in, - const v4sf *e, v4sf *out, int first) { - v4sf r0=in[0], i0=in[1], r1=in[2], i1=in[3], r2=in[4], i2=in[5], r3=in[6], i3=in[7]; - /* - transformation for each column is: - - [1 1 1 1 0 0 0 0] [r0] - [1 0 0 -1 0 -1 -1 0] [r1] - [1 -1 -1 1 0 0 0 0] [r2] - [1 0 0 -1 0 1 1 0] [r3] - [0 0 0 0 1 -1 1 -1] * [i0] - [0 -1 1 0 1 0 0 1] [i1] - [0 0 0 0 1 1 -1 -1] [i2] - [0 1 -1 0 1 0 0 1] [i3] - */ - - v4sf sr0 = VADD(r0,r3), dr0 = VSUB(r0,r3); - v4sf sr1 = VADD(r1,r2), dr1 = VSUB(r1,r2); - v4sf si0 = VADD(i0,i3), di0 = VSUB(i0,i3); - v4sf si1 = VADD(i1,i2), di1 = VSUB(i1,i2); - - r0 = VADD(sr0, sr1); - r2 = VSUB(sr0, sr1); - r1 = VSUB(dr0, si1); - r3 = VADD(dr0, si1); - i0 = VSUB(di0, di1); - i2 = VADD(di0, di1); - i1 = VSUB(si0, dr1); - i3 = VADD(si0, dr1); - - VCPLXMULCONJ(r1,i1,e[0],e[1]); - VCPLXMULCONJ(r2,i2,e[2],e[3]); - VCPLXMULCONJ(r3,i3,e[4],e[5]); - - VTRANSPOSE4(r0,r1,r2,r3); - VTRANSPOSE4(i0,i1,i2,i3); - - if (!first) { - *out++ = r0; - *out++ = i0; - } - *out++ = r1; - *out++ = i1; - *out++ = r2; - *out++ = i2; - *out++ = r3; - *out++ = i3; -} - -static NEVER_INLINE(void) pffft_real_preprocess(int Ncvec, const v4sf *in, v4sf *out, const v4sf *e) { - int k, dk = Ncvec/SIMD_SZ; /* number of 4x4 matrix blocks */ - /* fftpack order is f0r f1r f1i f2r f2i ... f(n-1)r f(n-1)i f(n)r */ - - v4sf_union Xr, Xi, *uout = (v4sf_union*)out; - float cr0, ci0, cr1, ci1, cr2, ci2, cr3, ci3; - static const float s = (float)M_SQRT2; - assert(in != out); - for (k=0; k < 4; ++k) { - Xr.f[k] = ((float*)in)[8*k]; - Xi.f[k] = ((float*)in)[8*k+4]; - } - - pffft_real_preprocess_4x4(in, e, out+1, 1); /* will write only 6 values */ - - /* - [Xr0 Xr1 Xr2 Xr3 Xi0 Xi1 Xi2 Xi3] - - [cr0] [1 0 2 0 1 0 0 0] - [cr1] [1 0 0 0 -1 0 -2 0] - [cr2] [1 0 -2 0 1 0 0 0] - [cr3] [1 0 0 0 -1 0 2 0] - [ci0] [0 2 0 2 0 0 0 0] - [ci1] [0 s 0 -s 0 -s 0 -s] - [ci2] [0 0 0 0 0 -2 0 2] - [ci3] [0 -s 0 s 0 -s 0 -s] - */ - for (k=1; k < dk; ++k) { - pffft_real_preprocess_4x4(in+8*k, e + k*6, out-1+k*8, 0); - } - - cr0=(Xr.f[0]+Xi.f[0]) + 2*Xr.f[2]; uout[0].f[0] = cr0; - cr1=(Xr.f[0]-Xi.f[0]) - 2*Xi.f[2]; uout[0].f[1] = cr1; - cr2=(Xr.f[0]+Xi.f[0]) - 2*Xr.f[2]; uout[0].f[2] = cr2; - cr3=(Xr.f[0]-Xi.f[0]) + 2*Xi.f[2]; uout[0].f[3] = cr3; - ci0= 2*(Xr.f[1]+Xr.f[3]); uout[2*Ncvec-1].f[0] = ci0; - ci1= s*(Xr.f[1]-Xr.f[3]) - s*(Xi.f[1]+Xi.f[3]); uout[2*Ncvec-1].f[1] = ci1; - ci2= 2*(Xi.f[3]-Xi.f[1]); uout[2*Ncvec-1].f[2] = ci2; - ci3=-s*(Xr.f[1]-Xr.f[3]) - s*(Xi.f[1]+Xi.f[3]); uout[2*Ncvec-1].f[3] = ci3; -} - - -static -void pffft_transform_internal(PFFFT_Setup *setup, const float *finput, float *foutput, v4sf *scratch, - pffft_direction_t direction, int ordered) { - int k, Ncvec = setup->Ncvec; - int nf_odd = (setup->ifac[1] & 1); - -#if 0 - /* temporary buffer is allocated on the stack if the scratch pointer is NULL */ - int stack_allocate = (scratch == 0 ? Ncvec*2 : 1); - VLA_ARRAY_ON_STACK(v4sf, scratch_on_stack, stack_allocate); -#endif - - const v4sf *vinput = (const v4sf*)finput; - v4sf *voutput = (v4sf*)foutput; - v4sf *buff[2]; - int ib = (nf_odd ^ ordered ? 1 : 0); - buff[0] = voutput; buff[1] = scratch; - - assert(VALIGNED(finput) && VALIGNED(foutput)); - - /*assert(finput != foutput); */ - if (direction == PFFFT_FORWARD) { - ib = !ib; - if (setup->transform == PFFFT_REAL) { - ib = (rfftf1_ps(Ncvec*2, vinput, buff[ib], buff[!ib], - setup->twiddle, &setup->ifac[0]) == buff[0] ? 0 : 1); - pffft_real_finalize(Ncvec, buff[ib], buff[!ib], (v4sf*)setup->e); - } else { - v4sf *tmp = buff[ib]; - for (k=0; k < Ncvec; ++k) { - UNINTERLEAVE2(vinput[k*2], vinput[k*2+1], tmp[k*2], tmp[k*2+1]); - } - ib = (cfftf1_ps(Ncvec, buff[ib], buff[!ib], buff[ib], - setup->twiddle, &setup->ifac[0], -1) == buff[0] ? 0 : 1); - pffft_cplx_finalize(Ncvec, buff[ib], buff[!ib], (v4sf*)setup->e); - } - if (ordered) { - pffft_zreorder(setup, (float*)buff[!ib], (float*)buff[ib], PFFFT_FORWARD); - } else ib = !ib; - } else { - if (vinput == buff[ib]) { - ib = !ib; /* may happen when finput == foutput */ - } - if (ordered) { - pffft_zreorder(setup, (float*)vinput, (float*)buff[ib], PFFFT_BACKWARD); - vinput = buff[ib]; ib = !ib; - } - if (setup->transform == PFFFT_REAL) { - pffft_real_preprocess(Ncvec, vinput, buff[ib], (v4sf*)setup->e); - ib = (rfftb1_ps(Ncvec*2, buff[ib], buff[0], buff[1], - setup->twiddle, &setup->ifac[0]) == buff[0] ? 0 : 1); - } else { - pffft_cplx_preprocess(Ncvec, vinput, buff[ib], (v4sf*)setup->e); - ib = (cfftf1_ps(Ncvec, buff[ib], buff[0], buff[1], - setup->twiddle, &setup->ifac[0], +1) == buff[0] ? 0 : 1); - for (k=0; k < Ncvec; ++k) { - INTERLEAVE2(buff[ib][k*2], buff[ib][k*2+1], buff[ib][k*2], buff[ib][k*2+1]); - } - } - } - - if (buff[ib] != voutput) { - /* extra copy required -- this situation should only happen when finput == foutput */ - assert(finput==foutput); - for (k=0; k < Ncvec; ++k) { - v4sf a = buff[ib][2*k], b = buff[ib][2*k+1]; - voutput[2*k] = a; voutput[2*k+1] = b; - } - ib = !ib; - } - assert(buff[ib] == voutput); -} - -#if 0 -void pffft_zconvolve_accumulate(PFFFT_Setup *s, const float *a, const float *b, float *ab, float scaling) { - int Ncvec = s->Ncvec; - const v4sf * RESTRICT va = (const v4sf*)a; - const v4sf * RESTRICT vb = (const v4sf*)b; - v4sf * RESTRICT vab = (v4sf*)ab; - -#ifdef __arm__ - __builtin_prefetch(va); - __builtin_prefetch(vb); - __builtin_prefetch(vab); - __builtin_prefetch(va+2); - __builtin_prefetch(vb+2); - __builtin_prefetch(vab+2); - __builtin_prefetch(va+4); - __builtin_prefetch(vb+4); - __builtin_prefetch(vab+4); - __builtin_prefetch(va+6); - __builtin_prefetch(vb+6); - __builtin_prefetch(vab+6); -# ifndef __clang__ -# define ZCONVOLVE_USING_INLINE_NEON_ASM -# endif -#endif - - float ar, ai, br, bi, abr, abi; -#ifndef ZCONVOLVE_USING_INLINE_ASM - v4sf vscal = LD_PS1(scaling); - int i; -#endif - - assert(VALIGNED(a) && VALIGNED(b) && VALIGNED(ab)); - ar = ((v4sf_union*)va)[0].f[0]; - ai = ((v4sf_union*)va)[1].f[0]; - br = ((v4sf_union*)vb)[0].f[0]; - bi = ((v4sf_union*)vb)[1].f[0]; - abr = ((v4sf_union*)vab)[0].f[0]; - abi = ((v4sf_union*)vab)[1].f[0]; - -#ifdef ZCONVOLVE_USING_INLINE_ASM /* inline asm version, unfortunately miscompiled by clang 3.2, at least on ubuntu.. so this will be restricted to gcc */ - const float *a_ = a, *b_ = b; float *ab_ = ab; - int N = Ncvec; - asm volatile("mov r8, %2 \n" - "vdup.f32 q15, %4 \n" - "1: \n" - "pld [%0,#64] \n" - "pld [%1,#64] \n" - "pld [%2,#64] \n" - "pld [%0,#96] \n" - "pld [%1,#96] \n" - "pld [%2,#96] \n" - "vld1.f32 {q0,q1}, [%0,:128]! \n" - "vld1.f32 {q4,q5}, [%1,:128]! \n" - "vld1.f32 {q2,q3}, [%0,:128]! \n" - "vld1.f32 {q6,q7}, [%1,:128]! \n" - "vld1.f32 {q8,q9}, [r8,:128]! \n" - - "vmul.f32 q10, q0, q4 \n" - "vmul.f32 q11, q0, q5 \n" - "vmul.f32 q12, q2, q6 \n" - "vmul.f32 q13, q2, q7 \n" - "vmls.f32 q10, q1, q5 \n" - "vmla.f32 q11, q1, q4 \n" - "vld1.f32 {q0,q1}, [r8,:128]! \n" - "vmls.f32 q12, q3, q7 \n" - "vmla.f32 q13, q3, q6 \n" - "vmla.f32 q8, q10, q15 \n" - "vmla.f32 q9, q11, q15 \n" - "vmla.f32 q0, q12, q15 \n" - "vmla.f32 q1, q13, q15 \n" - "vst1.f32 {q8,q9},[%2,:128]! \n" - "vst1.f32 {q0,q1},[%2,:128]! \n" - "subs %3, #2 \n" - "bne 1b \n" - : "+r"(a_), "+r"(b_), "+r"(ab_), "+r"(N) : "r"(scaling) : "r8", "q0","q1","q2","q3","q4","q5","q6","q7","q8","q9", "q10","q11","q12","q13","q15","memory"); -#else /* default routine, works fine for non-arm cpus with current compilers */ - for (i=0; i < Ncvec; i += 2) { - v4sf ar, ai, br, bi; - ar = va[2*i+0]; ai = va[2*i+1]; - br = vb[2*i+0]; bi = vb[2*i+1]; - VCPLXMUL(ar, ai, br, bi); - vab[2*i+0] = VMADD(ar, vscal, vab[2*i+0]); - vab[2*i+1] = VMADD(ai, vscal, vab[2*i+1]); - ar = va[2*i+2]; ai = va[2*i+3]; - br = vb[2*i+2]; bi = vb[2*i+3]; - VCPLXMUL(ar, ai, br, bi); - vab[2*i+2] = VMADD(ar, vscal, vab[2*i+2]); - vab[2*i+3] = VMADD(ai, vscal, vab[2*i+3]); - } -#endif - if (s->transform == PFFFT_REAL) { - ((v4sf_union*)vab)[0].f[0] = abr + ar*br*scaling; - ((v4sf_union*)vab)[1].f[0] = abi + ai*bi*scaling; - } -} -#endif - - -#else /* defined(PFFFT_SIMD_DISABLE) */ - -/* standard routine using scalar floats, without SIMD stuff. */ - -#define pffft_zreorder_nosimd pffft_zreorder -static -void pffft_zreorder_nosimd(PFFFT_Setup *setup, const float *in, float *out, pffft_direction_t direction) { - int k, N = setup->N; - if (setup->transform == PFFFT_COMPLEX) { - for (k=0; k < 2*N; ++k) out[k] = in[k]; - return; - } - else if (direction == PFFFT_FORWARD) { - float x_N = in[N-1]; - for (k=N-1; k > 1; --k) out[k] = in[k-1]; - out[0] = in[0]; - out[1] = x_N; - } else { - float x_N = in[1]; - for (k=1; k < N-1; ++k) out[k] = in[k+1]; - out[0] = in[0]; - out[N-1] = x_N; - } -} - -#define pffft_transform_internal_nosimd pffft_transform_internal -static -void pffft_transform_internal_nosimd(PFFFT_Setup *setup, const float *input, float *output, float *scratch, - pffft_direction_t direction, int ordered) { - int Ncvec = setup->Ncvec; - int nf_odd = (setup->ifac[1] & 1); - -#if 0 - /* temporary buffer is allocated on the stack if the scratch pointer is NULL */ - int stack_allocate = (scratch == 0 ? Ncvec*2 : 1); - VLA_ARRAY_ON_STACK(v4sf, scratch_on_stack, stack_allocate); -#endif - float *buff[2]; - int ib; - /* if (scratch == 0) scratch = scratch_on_stack; */ - buff[0] = output; buff[1] = scratch; - - if (setup->transform == PFFFT_COMPLEX) ordered = 0; /* it is always ordered. */ - ib = (nf_odd ^ ordered ? 1 : 0); - - if (direction == PFFFT_FORWARD) { - if (setup->transform == PFFFT_REAL) { - ib = (rfftf1_ps(Ncvec*2, input, buff[ib], buff[!ib], - setup->twiddle, &setup->ifac[0]) == buff[0] ? 0 : 1); - } else { - ib = (cfftf1_ps(Ncvec, input, buff[ib], buff[!ib], - setup->twiddle, &setup->ifac[0], -1) == buff[0] ? 0 : 1); - } - if (ordered) { - pffft_zreorder(setup, buff[ib], buff[!ib], PFFFT_FORWARD); ib = !ib; - } - } else { - if (input == buff[ib]) { - ib = !ib; /* may happen when finput == foutput */ - } - if (ordered) { - pffft_zreorder(setup, input, buff[!ib], PFFFT_BACKWARD); - input = buff[!ib]; - } - if (setup->transform == PFFFT_REAL) { - ib = (rfftb1_ps(Ncvec*2, input, buff[ib], buff[!ib], - setup->twiddle, &setup->ifac[0]) == buff[0] ? 0 : 1); - } else { - ib = (cfftf1_ps(Ncvec, input, buff[ib], buff[!ib], - setup->twiddle, &setup->ifac[0], +1) == buff[0] ? 0 : 1); - } - } - if (buff[ib] != output) { - int k; - /* extra copy required -- this situation should happens only when finput == foutput */ - assert(input==output); - for (k=0; k < Ncvec; ++k) { - float a = buff[ib][2*k], b = buff[ib][2*k+1]; - output[2*k] = a; output[2*k+1] = b; - } - ib = !ib; - } - assert(buff[ib] == output); -} - -#if 0 -#define pffft_zconvolve_accumulate_nosimd pffft_zconvolve_accumulate -void pffft_zconvolve_accumulate_nosimd(PFFFT_Setup *s, const float *a, const float *b, - float *ab, float scaling) { - int i, Ncvec = s->Ncvec; - - if (s->transform == PFFFT_REAL) { - /* take care of the fftpack ordering */ - ab[0] += a[0]*b[0]*scaling; - ab[2*Ncvec-1] += a[2*Ncvec-1]*b[2*Ncvec-1]*scaling; - ++ab; ++a; ++b; --Ncvec; - } - for (i=0; i < Ncvec; ++i) { - float ar, ai, br, bi; - ar = a[2*i+0]; ai = a[2*i+1]; - br = b[2*i+0]; bi = b[2*i+1]; - VCPLXMUL(ar, ai, br, bi); - ab[2*i+0] += ar*scaling; - ab[2*i+1] += ai*scaling; - } -} -#endif - -#endif /* defined(PFFFT_SIMD_DISABLE) */ - -static -void pffft_transform(PFFFT_Setup *setup, const float *input, float *output, float *work, pffft_direction_t direction) { - pffft_transform_internal(setup, input, output, (v4sf*)work, direction, 0); -} - -static -void pffft_transform_ordered(PFFFT_Setup *setup, const float *input, float *output, float *work, pffft_direction_t direction) { - pffft_transform_internal(setup, input, output, (v4sf*)work, direction, 1); -} - -#endif diff --git a/C/src/soxr-0.1.3/src/pffft.h b/C/src/soxr-0.1.3/src/pffft.h deleted file mode 100644 index 63522cac..00000000 --- a/C/src/soxr-0.1.3/src/pffft.h +++ /dev/null @@ -1,197 +0,0 @@ -/* https://bitbucket.org/jpommier/pffft/raw/483453d8f7661058e74aa4e7cf5c27bcd7887e7a/pffft.h - * with minor changes for libsoxr. */ - -#if !defined PFFT_MACROS_ONLY - -/* Copyright (c) 2013 Julien Pommier ( pommier@modartt.com ) - - Based on original fortran 77 code from FFTPACKv4 from NETLIB, - authored by Dr Paul Swarztrauber of NCAR, in 1985. - - As confirmed by the NCAR fftpack software curators, the following - FFTPACKv5 license applies to FFTPACKv4 sources. My changes are - released under the same terms. - - FFTPACK license: - - http://www.cisl.ucar.edu/css/software/fftpack5/ftpk.html - - Copyright (c) 2004 the University Corporation for Atmospheric - Research ("UCAR"). All rights reserved. Developed by NCAR's - Computational and Information Systems Laboratory, UCAR, - www.cisl.ucar.edu. - - Redistribution and use of the Software in source and binary forms, - with or without modification, is permitted provided that the - following conditions are met: - - - Neither the names of NCAR's Computational and Information Systems - Laboratory, the University Corporation for Atmospheric Research, - nor the names of its sponsors or contributors may be used to - endorse or promote products derived from this Software without - specific prior written permission. - - - Redistributions of source code must retain the above copyright - notices, this list of conditions, and the disclaimer below. - - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions, and the disclaimer below in the - documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES OR OTHER LIABILITY, WHETHER IN AN - ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE - SOFTWARE. -*/ - -/* - PFFFT : a Pretty Fast FFT. - - This is basically an adaptation of the single precision fftpack - (v4) as found on netlib taking advantage of SIMD instruction found - on cpus such as intel x86 (SSE1), powerpc (Altivec), and arm (NEON). - - For architectures where no SIMD instruction is available, the code - falls back to a scalar version. - - Restrictions: - - - 1D transforms only, with 32-bit single precision. - - - supports only transforms for inputs of length N of the form - N=(2^a)*(3^b)*(5^c), a >= 5, b >=0, c >= 0 (32, 48, 64, 96, 128, - 144, 160, etc are all acceptable lengths). Performance is best for - 128<=N<=8192. - - - all (float*) pointers in the functions below are expected to - have an "simd-compatible" alignment, that is 16 bytes on x86 and - powerpc CPUs. - - You can allocate such buffers with the functions - pffft_aligned_malloc / pffft_aligned_free (or with stuff like - posix_memalign..) - -*/ - -#ifndef PFFFT_H -#define PFFFT_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#if PFFFT_DOUBLE -#define float double -#endif - - /* opaque struct holding internal stuff (precomputed twiddle factors) - this struct can be shared by many threads as it contains only - read-only data. - */ - typedef struct PFFFT_Setup PFFFT_Setup; - - /* direction of the transform */ - typedef enum { PFFFT_FORWARD, PFFFT_BACKWARD } pffft_direction_t; - - /* type of transform */ - typedef enum { PFFFT_REAL, PFFFT_COMPLEX } pffft_transform_t; - - /* - prepare for performing transforms of size N -- the returned - PFFFT_Setup structure is read-only so it can safely be shared by - multiple concurrent threads. - */ - static - PFFFT_Setup *pffft_new_setup(int N, pffft_transform_t transform); - static - void pffft_destroy_setup(PFFFT_Setup *); - /* - Perform a Fourier transform , The z-domain data is stored in the - most efficient order for transforming it back, or using it for - convolution. If you need to have its content sorted in the - "usual" way, that is as an array of interleaved complex numbers, - either use pffft_transform_ordered , or call pffft_zreorder after - the forward fft, and before the backward fft. - - Transforms are not scaled: PFFFT_BACKWARD(PFFFT_FORWARD(x)) = N*x. - Typically you will want to scale the backward transform by 1/N. - - The 'work' pointer should point to an area of N (2*N for complex - fft) floats, properly aligned. If 'work' is NULL, then stack will - be used instead (this is probably the best strategy for small - FFTs, say for N < 16384). - - input and output may alias. - */ - static - void pffft_transform(PFFFT_Setup *setup, const float *input, float *output, float *work, pffft_direction_t direction); - - /* - Similar to pffft_transform, but makes sure that the output is - ordered as expected (interleaved complex numbers). This is - similar to calling pffft_transform and then pffft_zreorder. - - input and output may alias. - */ - static - void pffft_transform_ordered(PFFFT_Setup *setup, const float *input, float *output, float *work, pffft_direction_t direction); - - /* - call pffft_zreorder(.., PFFFT_FORWARD) after pffft_transform(..., - PFFFT_FORWARD) if you want to have the frequency components in - the correct "canonical" order, as interleaved complex numbers. - - (for real transforms, both 0-frequency and half frequency - components, which are real, are assembled in the first entry as - F(0)+i*F(n/2+1). Note that the original fftpack did place - F(n/2+1) at the end of the arrays). - - input and output should not alias. - */ - static - void pffft_zreorder(PFFFT_Setup *setup, const float *input, float *output, pffft_direction_t direction); - - /* - Perform a multiplication of the frequency components of dft_a and - dft_b and accumulate them into dft_ab. The arrays should have - been obtained with pffft_transform(.., PFFFT_FORWARD) and should - *not* have been reordered with pffft_zreorder (otherwise just - perform the operation yourself as the dft coefs are stored as - interleaved complex numbers). - - the operation performed is: dft_ab += (dft_a * fdt_b)*scaling - - The dft_a, dft_b and dft_ab pointers may alias. - */ - void pffft_zconvolve_accumulate(PFFFT_Setup *setup, const float *dft_a, const float *dft_b, float *dft_ab, float scaling); - - /* - the float buffers must have the correct alignment (16-byte boundary - on intel and powerpc). This function may be used to obtain such - correctly aligned buffers. - */ -#if 0 - void *pffft_aligned_malloc(size_t nb_bytes); - void pffft_aligned_free(void *); - - /* return 4 or 1 wether support SSE/Altivec instructions was enable when building pffft.c */ - int pffft_simd_size(); -#endif - -#undef float - -#ifdef __cplusplus -} -#endif - -#endif - -#endif diff --git a/C/src/soxr-0.1.3/src/pffft32.c b/C/src/soxr-0.1.3/src/pffft32.c deleted file mode 100644 index f4808094..00000000 --- a/C/src/soxr-0.1.3/src/pffft32.c +++ /dev/null @@ -1,39 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#define SIMD_ALIGNED_FREE free -#define SIMD_ALIGNED_MALLOC malloc -#define PFFFT_SIMD_DISABLE -#define PFFFT_DOUBLE 0 -#include "pffft-wrap.c" - -#include "filter.h" -#include "rdft_t.h" - -static void * setup(int len) {return pffft_new_setup(len, PFFFT_REAL);} -static void delete_setup(void * setup) {pffft_destroy_setup(setup);} -static void forward (int length, void * setup, float * h, float * scratch) {pffft_transform (setup, h, h, scratch, PFFFT_FORWARD); (void)length;} -static void oforward (int length, void * setup, float * h, float * scratch) {pffft_transform_ordered(setup, h, h, scratch, PFFFT_FORWARD); (void)length;} -static void backward (int length, void * setup, float * H, float * scratch) {pffft_transform (setup, H, H, scratch, PFFFT_BACKWARD);(void)length;} -static void obackward(int length, void * setup, float * H, float * scratch) {pffft_transform_ordered(setup, H, H, scratch, PFFFT_BACKWARD);(void)length;} -static void convolve(int length, void * setup, float * H, float const * with) { pffft_zconvolve(setup, H, with, H); (void)length;} -static int multiplier(void) {return 1;} -static int flags(void) {return RDFT_NEEDS_SCRATCH;} - -fn_t _soxr_rdft32_cb[] = { - (fn_t)setup, - (fn_t)setup, - (fn_t)delete_setup, - (fn_t)forward, - (fn_t)oforward, - (fn_t)backward, - (fn_t)obackward, - (fn_t)convolve, - (fn_t)_soxr_ordered_partial_convolve_f, - (fn_t)multiplier, - (fn_t)pffft_reorder_back, - (fn_t)malloc, - (fn_t)calloc, - (fn_t)free, - (fn_t)flags, -}; diff --git a/C/src/soxr-0.1.3/src/pffft32s.c b/C/src/soxr-0.1.3/src/pffft32s.c deleted file mode 100644 index 7798a45c..00000000 --- a/C/src/soxr-0.1.3/src/pffft32s.c +++ /dev/null @@ -1,34 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#define PFFFT_DOUBLE 0 -#include "pffft-wrap.c" - -#include "rdft_t.h" - -static void * setup(int len) {return pffft_new_setup(len, PFFFT_REAL);} -static void forward (int length, void * setup, float * h, float * scratch) {pffft_transform (setup, h, h, scratch, PFFFT_FORWARD); (void)length;} -static void oforward (int length, void * setup, float * h, float * scratch) {pffft_transform_ordered(setup, h, h, scratch, PFFFT_FORWARD); (void)length;} -static void backward (int length, void * setup, float * H, float * scratch) {pffft_transform (setup, H, H, scratch, PFFFT_BACKWARD);(void)length;} -static void obackward(int length, void * setup, float * H, float * scratch) {pffft_transform_ordered(setup, H, H, scratch, PFFFT_BACKWARD);(void)length;} -static void convolve(int length, void * setup, float * H, float const * with) {pffft_zconvolve(setup, H, with, H); (void)length;} -static int multiplier(void) {return 1;} -static int flags(void) {return RDFT_IS_SIMD | RDFT_NEEDS_SCRATCH;} - -fn_t _soxr_rdft32s_cb[] = { - (fn_t)setup, - (fn_t)setup, - (fn_t)pffft_destroy_setup, - (fn_t)forward, - (fn_t)oforward, - (fn_t)backward, - (fn_t)obackward, - (fn_t)convolve, - (fn_t)ORDERED_PARTIAL_CONVOLVE_SIMD, - (fn_t)multiplier, - (fn_t)pffft_reorder_back, - (fn_t)SIMD_ALIGNED_MALLOC, - (fn_t)SIMD_ALIGNED_CALLOC, - (fn_t)SIMD_ALIGNED_FREE, - (fn_t)flags, -}; diff --git a/C/src/soxr-0.1.3/src/pffft64s.c b/C/src/soxr-0.1.3/src/pffft64s.c deleted file mode 100644 index 7c37c9d4..00000000 --- a/C/src/soxr-0.1.3/src/pffft64s.c +++ /dev/null @@ -1,34 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#define PFFFT_DOUBLE 1 -#include "pffft-wrap.c" - -#include "rdft_t.h" - -static void * setup(int len) {return pffft_new_setup(len, PFFFT_REAL);} -static void forward (int length, void * setup, double * h, double * scratch) {pffft_transform (setup, h, h, scratch, PFFFT_FORWARD); (void)length;} -static void oforward (int length, void * setup, double * h, double * scratch) {pffft_transform_ordered(setup, h, h, scratch, PFFFT_FORWARD); (void)length;} -static void backward (int length, void * setup, double * H, double * scratch) {pffft_transform (setup, H, H, scratch, PFFFT_BACKWARD);(void)length;} -static void obackward(int length, void * setup, double * H, double * scratch) {pffft_transform_ordered(setup, H, H, scratch, PFFFT_BACKWARD);(void)length;} -static void convolve(int length, void * setup, double * H, double const * with) {pffft_zconvolve(setup, H, with, H); (void)length;} -static int multiplier(void) {return 1;} -static int flags(void) {return RDFT_IS_SIMD | RDFT_NEEDS_SCRATCH;} - -fn_t _soxr_rdft64s_cb[] = { - (fn_t)setup, - (fn_t)setup, - (fn_t)pffft_destroy_setup, - (fn_t)forward, - (fn_t)oforward, - (fn_t)backward, - (fn_t)obackward, - (fn_t)convolve, - (fn_t)ORDERED_PARTIAL_CONVOLVE_SIMD, - (fn_t)multiplier, - (fn_t)pffft_reorder_back, - (fn_t)SIMD_ALIGNED_MALLOC, - (fn_t)SIMD_ALIGNED_CALLOC, - (fn_t)SIMD_ALIGNED_FREE, - (fn_t)flags, -}; diff --git a/C/src/soxr-0.1.3/src/poly-fir.h b/C/src/soxr-0.1.3/src/poly-fir.h deleted file mode 100644 index d138e030..00000000 --- a/C/src/soxr-0.1.3/src/poly-fir.h +++ /dev/null @@ -1,150 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -/* Resample using an interpolated poly-phase FIR with length LEN. */ -/* Input must be followed by FIR_LENGTH-1 samples. */ - -#if COEF_INTERP != 1 && COEF_INTERP != 2 && COEF_INTERP != 3 - #error COEF_INTERP -#endif - -#if SIMD_AVX || SIMD_SSE || SIMD_NEON - #define N (FIR_LENGTH>>2) - - #if COEF_INTERP == 1 - #define _ sum=vMac(vMac(b,X,a),vLdu(in+j*4),sum), ++j; - #elif COEF_INTERP == 2 - #define _ sum=vMac(vMac(vMac(c,X,b),X,a),vLdu(in+j*4),sum), ++j; - #else - #define _ sum=vMac(vMac(vMac(vMac(d,X,c),X,b),X,a),vLdu(in+j*4),sum), ++j; - #endif - - #define a coefs[(COEF_INTERP+1)*(N*phase+j)+(COEF_INTERP-0)] - #define b coefs[(COEF_INTERP+1)*(N*phase+j)+(COEF_INTERP-1)] - #define c coefs[(COEF_INTERP+1)*(N*phase+j)+(COEF_INTERP-2)] - #define d coefs[(COEF_INTERP+1)*(N*phase+j)+(COEF_INTERP-3)] - - #define BEGINNING v4_t X = vLds(x), sum = vZero(); \ - v4_t const * const __restrict coefs = (v4_t *)COEFS - #define END vStorSum(output+i, sum) - #define cc(n) case n: core(n); break - #define CORE(n) switch (n) {cc(2); cc(3); cc(4); cc(5); cc(6); default: core(n);} -#else - #define N FIR_LENGTH - - #if COEF_INTERP == 1 - #define _ sum += (b*x + a)*in[j], ++j; - #elif COEF_INTERP == 2 - #define _ sum += ((c*x + b)*x + a)*in[j], ++j; - #else - #define _ sum += (((d*x + c)*x + b)*x + a)*in[j], ++j; - #endif - - #define a (coef(COEFS, COEF_INTERP, N, phase, 0,j)) - #define b (coef(COEFS, COEF_INTERP, N, phase, 1,j)) - #define c (coef(COEFS, COEF_INTERP, N, phase, 2,j)) - #define d (coef(COEFS, COEF_INTERP, N, phase, 3,j)) - - #define BEGINNING sample_t sum = 0 - #define END output[i] = sum - #define CORE(n) core(n) -#endif - - - -#define floatPrecCore(n) { \ - float_step_t at = p->at.flt; \ - for (i = 0; (int)at < num_in; ++i, at += p->step.flt) { \ - sample_t const * const __restrict in = input + (int)at; \ - float_step_t frac = at - (int)at; \ - int phase = (int)(frac * (1 << PHASE_BITS)); \ - sample_t x = (sample_t)(frac * (1 << PHASE_BITS) - phase); \ - int j = 0; \ - BEGINNING; CONVOLVE(n); END; \ - } \ - fifo_read(&p->fifo, (int)at, NULL); \ - p->at.flt = at - (int)at; } /* Could round to 1 in some cirmcumstances. */ - - - -#define highPrecCore(n) { \ - step_t at; at.fix = p->at.fix; \ - for (i = 0; at.integer < num_in; ++i, \ - at.fix.ls.all += p->step.fix.ls.all, \ - at.whole += p->step.whole + (at.fix.ls.all < p->step.fix.ls.all)) { \ - sample_t const * const __restrict in = input + at.integer; \ - uint32_t frac = at.fraction; \ - int phase = (int)(frac >> (32 - PHASE_BITS)); /* High-order bits */ \ - /* Low-order bits, scaled to [0,1): */ \ - sample_t x = (sample_t)((frac << PHASE_BITS) * (1 / MULT32)); \ - int j = 0; \ - BEGINNING; CONVOLVE(n); END; \ - } \ - fifo_read(&p->fifo, at.integer, NULL); \ - p->at.whole = at.fraction; \ - p->at.fix.ls = at.fix.ls; } - - - -#define stdPrecCore(n) { \ - int64p_t at; at.all = p->at.whole; \ - for (i = 0; at.parts.ms < num_in; ++i, at.all += p->step.whole) { \ - sample_t const * const __restrict in = input + at.parts.ms; \ - uint32_t const frac = at.parts.ls; \ - int phase = (int)(frac >> (32 - PHASE_BITS)); /* high-order bits */ \ - /* Low-order bits, scaled to [0,1): */ \ - sample_t x = (sample_t)((frac << PHASE_BITS) * (1 / MULT32)); \ - int j = 0; \ - BEGINNING; CONVOLVE(n); END; \ - } \ - fifo_read(&p->fifo, at.parts.ms, NULL); \ - p->at.whole = at.parts.ls; } - - - -#if WITH_FLOAT_STD_PREC_CLOCK - #define SPCORE floatPrecCore -#else - #define SPCORE stdPrecCore -#endif - - - -#if WITH_HI_PREC_CLOCK - #define core(n) if (p->use_hi_prec_clock) highPrecCore(n) else SPCORE(n) -#else - #define core(n) SPCORE(n) -#endif - - - -static void FUNCTION(stage_t * p, fifo_t * output_fifo) -{ - sample_t const * input = stage_read_p(p); - int num_in = min(stage_occupancy(p), p->input_size); - int i, max_num_out = 1 + (int)(num_in * p->out_in_ratio); - sample_t * const __restrict output = fifo_reserve(output_fifo, max_num_out); - - CORE(N); - assert(max_num_out - i >= 0); - fifo_trim_by(output_fifo, max_num_out - i); -} - - - -#undef _ -#undef a -#undef b -#undef c -#undef d -#undef CORE -#undef cc -#undef core -#undef COEF_INTERP -#undef N -#undef BEGINNING -#undef END -#undef CONVOLVE -#undef FIR_LENGTH -#undef FUNCTION -#undef PHASE_BITS diff --git a/C/src/soxr-0.1.3/src/poly-fir0.h b/C/src/soxr-0.1.3/src/poly-fir0.h deleted file mode 100644 index 76fca2d6..00000000 --- a/C/src/soxr-0.1.3/src/poly-fir0.h +++ /dev/null @@ -1,56 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -/* Resample using a non-interpolated poly-phase FIR with length LEN. */ -/* Input must be followed by FIR_LENGTH-1 samples. */ - -#if SIMD_AVX || SIMD_SSE || SIMD_NEON - #define N (FIR_LENGTH>>2) - #define BEGINNING v4_t sum = vZero(); \ - v4_t const * const __restrict coefs = (v4_t *)COEFS + N * rem; - #define _ sum = vMac(vLdu(at+j*4), coefs[j], sum), ++j; - #define END vStorSum(output+i, sum) - #define cc(n) case n: core(n); break - #define CORE(n) switch (n) {cc(2); cc(3); cc(4); cc(5); cc(6); default: core(n);} -#else - #define N FIR_LENGTH - #define BEGINNING sample_t sum = 0; \ - sample_t const * const __restrict coefs = (sample_t *)COEFS + N * rem; - #define _ sum += coefs[j]*at[j], ++j; - #define END output[i] = sum - #define CORE(n) core(n) -#endif - -#define core(n) \ - for (i = 0; at < num_in * p->L; ++i, at += step) { \ - int const div = at / p->L, rem = at % p->L; \ - sample_t const * const __restrict at = input + div; \ - int j = 0; BEGINNING; CONVOLVE(n); END;} - -static void FUNCTION(stage_t * p, fifo_t * output_fifo) -{ - int num_in = min(stage_occupancy(p), p->input_size); - if (num_in) { - sample_t const * input = stage_read_p(p); - int at = p->at.integer, step = p->step.integer; - int i, num_out = (num_in * p->L - at + step - 1) / step; - sample_t * __restrict output = fifo_reserve(output_fifo, num_out); - - CORE(N); - assert(i == num_out); - fifo_read(&p->fifo, at / p->L, NULL); - p->at.integer = at % p->L; - } -} - -#undef _ -#undef CORE -#undef cc -#undef core -#undef N -#undef BEGINNING -#undef MIDDLE -#undef END -#undef CONVOLVE -#undef FIR_LENGTH -#undef FUNCTION diff --git a/C/src/soxr-0.1.3/src/rdft.h b/C/src/soxr-0.1.3/src/rdft.h deleted file mode 100644 index 59ba1741..00000000 --- a/C/src/soxr-0.1.3/src/rdft.h +++ /dev/null @@ -1,31 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -void ORDERED_CONVOLVE(int n, void * not_used, DFT_FLOAT * a, const DFT_FLOAT * b) -{ - int i; - a[0] *= b[0]; - a[1] *= b[1]; - for (i = 2; i < n; i += 2) { - DFT_FLOAT tmp = a[i]; - a[i ] = b[i ] * tmp - b[i+1] * a[i+1]; - a[i+1] = b[i+1] * tmp + b[i ] * a[i+1]; - } - (void)not_used; -} - -void ORDERED_PARTIAL_CONVOLVE(int n, DFT_FLOAT * a, const DFT_FLOAT * b) -{ - int i; - a[0] *= b[0]; - for (i = 2; i < n; i += 2) { - DFT_FLOAT tmp = a[i]; - a[i ] = b[i ] * tmp - b[i+1] * a[i+1]; - a[i+1] = b[i+1] * tmp + b[i ] * a[i+1]; - } - a[1] = b[i] * a[i] - b[i+1] * a[i+1]; -} - -#undef ORDERED_CONVOLVE -#undef ORDERED_PARTIAL_CONVOLVE -#undef DFT_FLOAT diff --git a/C/src/soxr-0.1.3/src/rdft_t.h b/C/src/soxr-0.1.3/src/rdft_t.h deleted file mode 100644 index 293d9c37..00000000 --- a/C/src/soxr-0.1.3/src/rdft_t.h +++ /dev/null @@ -1,24 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-13 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -typedef void (* fn_t)(void); - -#define rdft_forward_setup (*(void * (*)(int))RDFT_CB[0]) -#define rdft_backward_setup (*(void * (*)(int))RDFT_CB[1]) -#define rdft_delete_setup (*(void (*)(void *))RDFT_CB[2]) -#define rdft_forward (*(void (*)(int, void *, void *, void *))RDFT_CB[3]) -#define rdft_oforward (*(void (*)(int, void *, void *, void *))RDFT_CB[4]) -#define rdft_backward (*(void (*)(int, void *, void *, void *))RDFT_CB[5]) -#define rdft_obackward (*(void (*)(int, void *, void *, void *))RDFT_CB[6]) -#define rdft_convolve (*(void (*)(int, void *, void *, void const *))RDFT_CB[7]) -#define rdft_convolve_portion (*(void (*)(int, void *, void const *))RDFT_CB[8]) -#define rdft_multiplier (*(int (*)(void))RDFT_CB[9]) -#define rdft_reorder_back (*(void (*)(int, void *, void *, void *))RDFT_CB[10]) -#define rdft_malloc (*(void * (*)(size_t))RDFT_CB[11]) -#define rdft_calloc (*(void * (*)(size_t, size_t))RDFT_CB[12]) -#define rdft_free (*(void (*)(void *))RDFT_CB[13]) -#define rdft_flags (*(int (*)(void))RDFT_CB[14]) - -/* Flag templates: */ -#define RDFT_IS_SIMD 1 -#define RDFT_NEEDS_SCRATCH 2 diff --git a/C/src/soxr-0.1.3/src/rint-clip.h b/C/src/soxr-0.1.3/src/rint-clip.h deleted file mode 100644 index bfb64584..00000000 --- a/C/src/soxr-0.1.3/src/rint-clip.h +++ /dev/null @@ -1,158 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#if defined DITHER - -#define DITHERING + (1./32)*(int)(((ran1>>=3)&31)-((ran2>>=3)&31)) -#define DITHER_RAND (seed = 1664525UL * seed + 1013904223UL) >> 3 -#define DITHER_VARS unsigned long ran1 = DITHER_RAND, ran2 = DITHER_RAND -#define SEED_ARG , unsigned long * seed0 -#define SAVE_SEED *seed0 = seed -#define COPY_SEED unsigned long seed = *seed0; -#define COPY_SEED1 unsigned long seed1 = seed -#define PASS_SEED1 , &seed1 -#define PASS_SEED , &seed -#define FLOATD double - -#else - -#define DITHERING -#define DITHER_VARS -#define SEED_ARG -#define SAVE_SEED -#define COPY_SEED -#define COPY_SEED1 -#define PASS_SEED1 -#define PASS_SEED -#define FLOATD FLOATX - -#endif - -#define DO_16 _;_;_;_;_;_;_;_;_;_;_;_;_;_;_;_ - - - -#if defined FE_INVALID && defined FPU_RINT -static void RINT_CLIP(RINT_T * const dest, FLOATX const * const src, - unsigned stride, size_t i, size_t const n, size_t * const clips SEED_ARG) -{ - COPY_SEED - DITHER_VARS; - for (; i < n; ++i) { - FLOATD const d = src[i] DITHERING; - RINT(dest[stride * i], d); - if (fe_test_invalid()) { - fe_clear_invalid(); - dest[stride * i] = d > 0? RINT_MAX : -RINT_MAX - 1; - ++*clips; - } - } - SAVE_SEED; -} -#endif - - - -static size_t LSX_RINT_CLIP(void * * const dest0, FLOATX const * const src, - size_t const n SEED_ARG) -{ - size_t i, clips = 0; - RINT_T * dest = *dest0; - COPY_SEED -#if defined FE_INVALID && defined FPU_RINT -#define _ RINT(dest[i], src[i] DITHERING); ++i - for (i = 0; i < (n & ~15u);) { - COPY_SEED1; - DITHER_VARS; - DO_16; - if (fe_test_invalid()) { - fe_clear_invalid(); - RINT_CLIP(dest, src, 1, i - 16, i, &clips PASS_SEED1); - } - } - RINT_CLIP(dest, src, 1, i, n, &clips PASS_SEED); -#else -#define _ d = src[i] DITHERING, dest[i++] = (RINT_T)(d > 0? \ - d+.5 >= N? ++clips, N-1 : d+.5 : d-.5 <= -N-1? ++clips, -N:d-.5) - const double N = 1. + RINT_MAX; - double d; - for (i = 0; i < (n & ~15u);) { - DITHER_VARS; - DO_16; - } - { - DITHER_VARS; - for (; i < n; _); - } -#endif - SAVE_SEED; - *dest0 = dest + n; - return clips; -} -#undef _ - - - -static size_t LSX_RINT_CLIP_2(void * * dest0, FLOATX const * const * srcs, - unsigned const stride, size_t const n SEED_ARG) -{ - unsigned j; - size_t i, clips = 0; - RINT_T * dest = *dest0; - COPY_SEED -#if defined FE_INVALID && defined FPU_RINT -#define _ RINT(dest[stride * i], src[i] DITHERING); ++i - for (j = 0; j < stride; ++j, ++dest) { - FLOATX const * const src = srcs[j]; - for (i = 0; i < (n & ~15u);) { - COPY_SEED1; - DITHER_VARS; - DO_16; - if (fe_test_invalid()) { - fe_clear_invalid(); - RINT_CLIP(dest, src, stride, i - 16, i, &clips PASS_SEED1); - } - } - RINT_CLIP(dest, src, stride, i, n, &clips PASS_SEED); - } -#else -#define _ d = src[i] DITHERING, dest[stride * i++] = (RINT_T)(d > 0? \ - d+.5 >= N? ++clips, N-1 : d+.5 : d-.5 <= -N-1? ++clips, -N:d-.5) - const double N = 1. + RINT_MAX; - double d; - for (j = 0; j < stride; ++j, ++dest) { - FLOATX const * const src = srcs[j]; - for (i = 0; i < (n & ~15u);) { - DITHER_VARS; - DO_16; - } - { - DITHER_VARS; - for (; i < n; _); - } - } -#endif - SAVE_SEED; - *dest0 = dest + stride * (n - 1); - return clips; -} -#undef _ - -#undef FLOATD -#undef PASS_SEED -#undef PASS_SEED1 -#undef COPY_SEED1 -#undef COPY_SEED -#undef SAVE_SEED -#undef SEED_ARG -#undef DITHER_VARS -#undef DITHERING -#undef DITHER - -#undef RINT_MAX -#undef RINT_T -#undef FPU_RINT -#undef RINT -#undef RINT_CLIP -#undef LSX_RINT_CLIP -#undef LSX_RINT_CLIP_2 diff --git a/C/src/soxr-0.1.3/src/rint.h b/C/src/soxr-0.1.3/src/rint.h deleted file mode 100644 index 2f1dfbed..00000000 --- a/C/src/soxr-0.1.3/src/rint.h +++ /dev/null @@ -1,102 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#if !defined soxr_rint_included -#define soxr_rint_included - -#include "std-types.h" - -/* For x86, compiler-supplied versions of these functions (where available) - * can have poor performance (e.g. mingw32), so prefer these asm versions: */ - -#if defined __GNUC__ && (defined __i386__ || defined __x86_64__) - #define FPU_RINT32 - #define FPU_RINT16 - #define rint32D(a,b) __asm__ __volatile__("fistpl %0": "=m"(a): "t"(b): "st") - #define rint16D(a,b) __asm__ __volatile__("fistps %0": "=m"(a): "t"(b): "st") - #define rint32F rint32D - #define rint16F rint16D - #define FE_INVALID 1 - static __inline int fe_test_invalid(void) { - int status_word; - __asm__ __volatile__("fnstsw %%ax": "=a"(status_word)); - return status_word & FE_INVALID; - } - static __inline int fe_clear_invalid(void) { - int32_t status[7]; - __asm__ __volatile__("fnstenv %0": "=m"(status)); - status[1] &= ~FE_INVALID; - __asm__ __volatile__("fldenv %0": : "m"(*status)); - return 0; - } -#elif defined _MSC_VER && defined _M_IX86 - #define FPU_RINT32 - #define FPU_RINT16 - #define rint_fn(N,Y,X) \ - static __inline void N(Y *y, X x) {Y t; {__asm fld x __asm fistp t} *y=t;} - rint_fn(rint32d, int32_t, double) - rint_fn(rint32f, int32_t, float ) - rint_fn(rint16d, int16_t, double) - rint_fn(rint16f, int16_t, float ) - #define rint32D(y,x) rint32d(&(y),x) - #define rint32F(y,x) rint32f(&(y),x) - #define rint16D(y,x) rint16d(&(y),x) - #define rint16F(y,x) rint16f(&(y),x) - #define FE_INVALID 1 - static __inline int fe_test_invalid(void) { - short status_word; - __asm fnstsw status_word - return status_word & FE_INVALID; - } - static __inline int fe_clear_invalid(void) { - int32_t status[7]; - __asm fnstenv status - status[1] &= ~FE_INVALID; - __asm fldenv status - return 0; - } -#elif defined _MSC_VER && defined _M_X64 - #include - #include - #define FPU_RINT32 - #define FPU_RINT16 - static __inline void rint32d(int32_t *y, double x) { - *y = _mm_cvtsd_si32(_mm_load_sd(&x));} - static __inline void rint32f(int32_t *y, float x) { - *y = _mm_cvtss_si32(_mm_load_ss(&x));} - static __inline void rint16d(int16_t *y, double x) { - x = x*65536+32738; *y = (int16_t)(_mm_cvtsd_si32(_mm_load_sd(&x)) >> 16);} - #define rint32D(y,x) rint32d(&(y),x) - #define rint32F(y,x) rint32f(&(y),x) - #define rint16D(y,x) rint16d(&(y),x) - #define rint16F(y,x) rint16d(&(y),(double)(x)) - #define FE_INVALID 1 - #define fe_test_invalid() (_statusfp() & _SW_INVALID) - #define fe_clear_invalid _clearfp /* Note: clears all. */ -#elif HAVE_LRINT && LONG_MAX == 2147483647L && HAVE_FENV_H - #include - #include - #define FPU_RINT32 - #define rint32D(y,x) ((y)=lrint(x)) - #define rint32F(y,x) ((y)=lrintf(x)) - #define fe_test_invalid() fetestexcept(FE_INVALID) - #define fe_clear_invalid() feclearexcept(FE_INVALID) -#endif - -#if !defined FPU_RINT32 - #define rint32D(y,x) ((y)=(int32_t)((x) < 0? x - .5 : x + .5)) - #define rint32F(y,x) rint32D(y,(double)(x)) -#endif - -#if !defined FPU_RINT16 - #define rint16D(y,x) ((y)=(int16_t)((x) < 0? x - .5 : x + .5)) - #define rint16F(y,x) rint16D(y,(double)(x)) -#endif - -static __inline int32_t rint32(double input) { - int32_t result; rint32D(result, input); return result;} - -static __inline int16_t rint16(double input) { - int16_t result; rint16D(result, input); return result;} - -#endif diff --git a/C/src/soxr-0.1.3/src/samplerate.h b/C/src/soxr-0.1.3/src/samplerate.h deleted file mode 100644 index 911cc5d0..00000000 --- a/C/src/soxr-0.1.3/src/samplerate.h +++ /dev/null @@ -1 +0,0 @@ -#include "soxr-lsr.h" diff --git a/C/src/soxr-0.1.3/src/soxr-lsr.c b/C/src/soxr-0.1.3/src/soxr-lsr.c deleted file mode 100644 index 58ab50a2..00000000 --- a/C/src/soxr-0.1.3/src/soxr-lsr.c +++ /dev/null @@ -1,198 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-18 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -/* Wrapper mostly compatible with `libsamplerate'. */ - -#include -#include -#include "soxr.h" -#include "soxr-lsr.h" -#include "rint.h" - - - -SRC_STATE *src_new(SRC_SRCTYPE id, int channels, SRC_ERROR * error) -{ - return src_callback_new(0, id, channels, error, 0); -} - - - -SRC_ERROR src_process(SRC_STATE *p, SRC_DATA * io) -{ - size_t idone , odone; - - if (!p || !io) return -1; - - soxr_set_error( - p, soxr_set_io_ratio(p, 1/io->src_ratio, (size_t)io->output_frames)); - - soxr_process(p, io->data_in, /* hack: */ - (size_t)(io->end_of_input? ~io->input_frames : io->input_frames), - &idone, io->data_out, (size_t)io->output_frames, &odone); - - io->input_frames_used = (long)idone, io->output_frames_gen = (long)odone; - return -!!soxr_error(p); -} - - - -SRC_ERROR src_set_ratio(SRC_STATE * p, double oi_ratio) -{ - return -!!soxr_set_io_ratio(p, 1/oi_ratio, 0); -} - - - -SRC_ERROR src_reset(SRC_STATE * p) -{ - return -!!soxr_clear(p); -} - - - -SRC_ERROR src_error(SRC_STATE * p) -{ - return -!!soxr_error(p); -} - - - -SRC_STATE * src_delete(SRC_STATE * p) -{ - soxr_delete(p); - return 0; -} - - - -SRC_STATE *src_callback_new(src_callback_t fn, - SRC_SRCTYPE id, int channels, SRC_ERROR * error0, void * p) -{ - soxr_quality_spec_t q_spec = soxr_quality_spec(SOXR_LSR0Q + (unsigned)id, 0); - char const * e = getenv("SOXR_LSR_NUM_THREADS"); - soxr_runtime_spec_t r_spec = soxr_runtime_spec(!(e && atoi(e) != 1)); - soxr_error_t error; - soxr_t soxr = 0; - - assert (channels > 0); - soxr = soxr_create(0, 0, (unsigned)channels, &error, 0, &q_spec, &r_spec); - - if (soxr) - error = soxr_set_input_fn(soxr, (soxr_input_fn_t)fn, p, 0); - - if (error0) - *error0 = -!!error; - - return soxr; -} - - - -long src_callback_read(SRC_STATE *p, double oi_ratio, long olen, float * obuf) -{ - if (!p || olen < 0) return -1; - - soxr_set_error(p, soxr_set_io_ratio(p, 1/oi_ratio, (size_t)olen)); - return (long)soxr_output(p, obuf, (size_t)olen); -} - - - -SRC_ERROR src_simple(SRC_DATA * io, SRC_SRCTYPE id, int channels) -{ - size_t idone, odone; - soxr_error_t error; - soxr_quality_spec_t q_spec = soxr_quality_spec(SOXR_LSR0Q + (unsigned)id, 0); - char const * e = getenv("SOXR_LSR_NUM_THREADS"); - soxr_runtime_spec_t r_spec = soxr_runtime_spec(!(e && atoi(e) != 1)); - - if (!io || channels<=0 || io->input_frames<0 || io->output_frames<0) return-1; - - error = soxr_oneshot(1, io->src_ratio, (unsigned)channels, io->data_in, - (size_t)io->input_frames, &idone, io->data_out, (size_t)io->output_frames, - &odone, 0, &q_spec, &r_spec); - - io->input_frames_used = (long)idone, io->output_frames_gen = (long)odone; - - return -!!error; -} - - - -char const * src_get_name(SRC_SRCTYPE id) -{ - static char const * const names[] = { - "LSR best sinc", "LSR medium sinc", "LSR fastest sinc", - "LSR ZOH", "LSR linear", "SoX VHQ"}; - - return (unsigned)id < 5u + !getenv("SOXR_LSR_STRICT")? names[id] : 0; -} - - - -char const * src_get_description(SRC_SRCTYPE id) -{ - return src_get_name(id); -} - - - -char const * src_get_version(void) -{ - return soxr_version(); -} - - - -char const * src_strerror(SRC_ERROR error) -{ - return error == 1? "Placeholder." : error ? "soxr error" : soxr_strerror(0); -} - - - -int src_is_valid_ratio(double oi_ratio) -{ - return getenv("SOXR_LSR_STRICT")? - oi_ratio >= 1./256 && oi_ratio <= 256 : oi_ratio > 0; -} - - - -void src_short_to_float_array(short const * src, float * dest, int len) -{ - assert (src && dest); - - while (len--) dest[len] = (float)(src[len] * (1 / (1. + SHRT_MAX))); -} - - - -void src_float_to_short_array(float const * src, short * dest, int len) -{ - double d, N = 1. + SHRT_MAX; - assert (src && dest); - - while (len--) d = src[len] * N, dest[len] = - (short)(d > N - 1? (short)(N - 1) : d < -N? (short)-N : rint16(d)); -} - - - -void src_int_to_float_array(int const * src, float * dest, int len) -{ - assert (src && dest); - while (len--) dest[len] = (float)(src[len] * (1 / (32768. * 65536.))); -} - - - -void src_float_to_int_array(float const * src, int * dest, int len) -{ - double d, N = 32768. * 65536.; /* N.B. int32, not int! (Also above fn.) */ - assert (src && dest); - - while (len--) d = src[len] * N, dest[len] = - d >= N - 1? (int)(N - 1) : d < -N? (int)(-N) : rint32(d); -} diff --git a/C/src/soxr-0.1.3/src/soxr-lsr.h b/C/src/soxr-0.1.3/src/soxr-lsr.h deleted file mode 100644 index b1cc2470..00000000 --- a/C/src/soxr-0.1.3/src/soxr-lsr.h +++ /dev/null @@ -1,78 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-18 robs@users.sourceforge.net - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* Wrapper compatible with `libsamplerate' (constant-rate). - * (Libsoxr's native API can be found in soxr.h). */ - -#if !defined SAMPLERATE_H -#define SAMPLERATE_H -#if defined __cplusplus - extern "C" { -#endif - -#if defined SOXR_DLL - #if defined soxr_lsr_EXPORTS - #define SOXR __declspec(dllexport) - #else - #define SOXR __declspec(dllimport) - #endif -#elif defined SOXR_VISIBILITY && defined __GNUC__ && (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 1) - #define SOXR __attribute__ ((visibility("default"))) -#else - #define SOXR -#endif - -typedef float SRC_SAMPLE; -enum SRC_SRCTYPE_e {SRC_SINC_BEST_QUALITY, SRC_SINC_MEDIUM_QUALITY, - SRC_SINC_FASTEST, SRC_ZERO_ORDER_HOLD, SRC_LINEAR}; -typedef int SRC_SRCTYPE; -typedef int SRC_ERROR; -typedef long (* src_callback_t)(void *, SRC_SAMPLE * *); -typedef struct soxr SRC_STATE; -typedef struct SRC_DATA { - SRC_SAMPLE * data_in, * data_out; - long input_frames, output_frames; - long input_frames_used, output_frames_gen; - int end_of_input; - double src_ratio; -} SRC_DATA; -SOXR SRC_STATE * src_new(SRC_SRCTYPE, int num_channels, SRC_ERROR *); -SOXR SRC_ERROR src_process (SRC_STATE *, SRC_DATA *); -SOXR SRC_ERROR src_set_ratio(SRC_STATE *, double); -SOXR SRC_ERROR src_reset (SRC_STATE *); -SOXR SRC_ERROR src_error (SRC_STATE *); -SOXR SRC_STATE * src_delete (SRC_STATE *); -SOXR SRC_STATE * src_callback_new( - src_callback_t, SRC_SRCTYPE, int, SRC_ERROR *, void *); -SOXR long src_callback_read( - SRC_STATE *, double src_ratio, long, SRC_SAMPLE *); -SOXR SRC_ERROR src_simple(SRC_DATA *, SRC_SRCTYPE, int); -SOXR char const * src_get_name(SRC_SRCTYPE); -SOXR char const * src_get_description(SRC_SRCTYPE); -SOXR char const * src_get_version(void); -SOXR char const * src_strerror(SRC_ERROR); -SOXR int src_is_valid_ratio(double); -SOXR void src_short_to_float_array(short const *, float *, int); -SOXR void src_float_to_short_array(float const *, short *, int); -SOXR void src_int_to_float_array(int const *, float *, int); -SOXR void src_float_to_int_array(float const *, int *, int); - -#undef SOXR -#if defined __cplusplus - } -#endif -#endif diff --git a/C/src/soxr-0.1.3/src/soxr-lsr.pc.in b/C/src/soxr-0.1.3/src/soxr-lsr.pc.in deleted file mode 100644 index 7b757576..00000000 --- a/C/src/soxr-0.1.3/src/soxr-lsr.pc.in +++ /dev/null @@ -1,5 +0,0 @@ -Name: ${LSR} -Description: ${DESCRIPTION_SUMMARY} (with libsamplerate-like bindings) -Version: ${PROJECT_VERSION} -Libs: -L${LIB_INSTALL_DIR} -l${LSR} -Cflags: -I${INCLUDE_INSTALL_DIR} diff --git a/C/src/soxr-0.1.3/src/soxr.c b/C/src/soxr-0.1.3/src/soxr.c deleted file mode 100644 index c2861ac7..00000000 --- a/C/src/soxr-0.1.3/src/soxr.c +++ /dev/null @@ -1,842 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-18 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#include -#include -#include -#include - -#include "soxr.h" -#include "data-io.h" -#include "internal.h" - -#if AVUTIL_FOUND - #include -#endif - - - -#if WITH_DEV_TRACE - -#include -#include - -int _soxr_trace_level; - -void _soxr_trace(char const * fmt, ...) -{ - va_list args; - va_start(args, fmt); - vfprintf(stderr, fmt, args); - fputc('\n', stderr); - va_end(args); -} - -#endif - - - -char const * soxr_version(void) -{ - return "libsoxr-" SOXR_THIS_VERSION_STR; -} - - - - -typedef void sample_t; /* float or double */ -typedef void (* fn_t)(void); -typedef fn_t control_block_t[10]; - -#define resampler_input (*(sample_t * (*)(void *, sample_t * samples, size_t n))p->control_block[0]) -#define resampler_process (*(void (*)(void *, size_t))p->control_block[1]) -#define resampler_output (*(sample_t const * (*)(void *, sample_t * samples, size_t * n))p->control_block[2]) -#define resampler_flush (*(void (*)(void *))p->control_block[3]) -#define resampler_close (*(void (*)(void *))p->control_block[4]) -#define resampler_delay (*(double (*)(void *))p->control_block[5]) -#define resampler_sizes (*(void (*)(size_t * shared, size_t * channel))p->control_block[6]) -#define resampler_create (*(char const * (*)(void * channel, void * shared, double io_ratio, soxr_quality_spec_t * q_spec, soxr_runtime_spec_t * r_spec, double scale))p->control_block[7]) -#define resampler_set_io_ratio (*(void (*)(void *, double io_ratio, size_t len))p->control_block[8]) -#define resampler_id (*(char const * (*)(void))p->control_block[9]) - -typedef void * resampler_t; /* For one channel. */ -typedef void * resampler_shared_t; /* Between channels. */ -typedef void (* deinterleave_t)(sample_t * * dest, - soxr_datatype_t data_type, void const * * src0, size_t n, unsigned ch); -typedef size_t (* interleave_t)(soxr_datatype_t data_type, void * * dest, - sample_t const * const * src, size_t, unsigned, unsigned long *); - -struct soxr { - unsigned num_channels; - double io_ratio; - soxr_error_t error; - soxr_quality_spec_t q_spec; - soxr_io_spec_t io_spec; - soxr_runtime_spec_t runtime_spec; - - void * input_fn_state; - soxr_input_fn_t input_fn; - size_t max_ilen; - - resampler_shared_t shared; - resampler_t * resamplers; - control_block_t control_block; - deinterleave_t deinterleave; - interleave_t interleave; - - void * * channel_ptrs; - size_t clips; - unsigned long seed; - int flushing; -}; - - - -#if WITH_CR32 || WITH_CR32S || WITH_CR64 || WITH_CR64S - #include "filter.h" -#else - #define lsx_to_3dB(x) ((x)/(x)) -#endif - - - -soxr_quality_spec_t soxr_quality_spec(unsigned long recipe, unsigned long flags) -{ - soxr_quality_spec_t spec, * p = &spec; - unsigned q = recipe & 0xf; /* TODO: move to soxr-lsr.c: */ - unsigned quality = q > SOXR_LSR2Q+2? SOXR_VHQ : q > SOXR_LSR2Q? SOXR_QQ : q; - double rej; - memset(p, 0, sizeof(*p)); - if (quality > SOXR_PRECISIONQ) { - p->e = "invalid quality type"; - return spec; - } - flags |= quality < SOXR_LSR0Q ? RESET_ON_CLEAR : 0; - p->phase_response = "\62\31\144"[(recipe & 0x30)>>4]; - p->stopband_begin = 1; - p->precision = - quality == SOXR_QQ ? 0 : - quality <= SOXR_16_BITQ ? 16 : - quality <= SOXR_32_BITQ ? 4 + quality * 4 : - quality <= SOXR_LSR2Q ? 55 - quality * 4 : /* TODO: move to soxr-lsr.c */ - 0; - rej = p->precision * linear_to_dB(2.); - p->flags = flags; - if (quality <= SOXR_32_BITQ || quality == SOXR_PRECISIONQ) { - #define LOW_Q_BW0 (1385 / 2048.) /* 0.67625 rounded to be a FP exact. */ - p->passband_end = quality == 1? LOW_Q_BW0 : 1 - .05 / lsx_to_3dB(rej); - if (quality <= 2) - p->flags &= ~SOXR_ROLLOFF_NONE, p->flags |= SOXR_ROLLOFF_MEDIUM; - } - else { /* TODO: move to soxr-lsr.c */ - static float const bw[] = {.931f, .832f, .663f}; - p->passband_end = bw[quality - SOXR_LSR0Q]; - if (quality == SOXR_LSR2Q) { - p->flags &= ~SOXR_ROLLOFF_NONE; - p->flags |= SOXR_ROLLOFF_LSR2Q | SOXR_PROMOTE_TO_LQ; - } - } - if (recipe & SOXR_STEEP_FILTER) - p->passband_end = 1 - .01 / lsx_to_3dB(rej); - return spec; -} - - - -char const * soxr_engine(soxr_t p) -{ - return resampler_id(); -} - - - -size_t * soxr_num_clips(soxr_t p) -{ - return &p->clips; -} - - - -soxr_error_t soxr_error(soxr_t p) -{ - return p->error; -} - - - -soxr_runtime_spec_t soxr_runtime_spec(unsigned num_threads) -{ - soxr_runtime_spec_t spec, * p = &spec; - memset(p, 0, sizeof(*p)); - p->log2_min_dft_size = 10; - p->log2_large_dft_size = 17; - p->coef_size_kbytes = 400; - p->num_threads = num_threads; - return spec; -} - - - -soxr_io_spec_t soxr_io_spec( - soxr_datatype_t itype, - soxr_datatype_t otype) -{ - soxr_io_spec_t spec, * p = &spec; - memset(p, 0, sizeof(*p)); - if ((itype | otype) >= SOXR_SPLIT * 2) - p->e = "invalid io datatype(s)"; - else { - p->itype = itype; - p->otype = otype; - p->scale = 1; - } - return spec; -} - - - -#if (WITH_CR32S && WITH_CR32) || (WITH_CR64S && WITH_CR64) - #if defined __GNUC__ && defined __x86_64__ - #define CPUID(type, eax_, ebx_, ecx_, edx_) \ - __asm__ __volatile__ ( \ - "cpuid \n\t" \ - : "=a" (eax_), "=b" (ebx_), "=c" (ecx_), "=d" (edx_) \ - : "a" (type), "c" (0)); - #elif defined __GNUC__ && defined __i386__ - #define CPUID(type, eax_, ebx_, ecx_, edx_) \ - __asm__ __volatile__ ( \ - "mov %%ebx, %%edi \n\t" \ - "cpuid \n\t" \ - "xchg %%edi, %%ebx \n\t" \ - : "=a" (eax_), "=D" (ebx_), "=c" (ecx_), "=d" (edx_) \ - : "a" (type), "c" (0)); - #elif defined _M_X64 && defined _MSC_VER && _MSC_VER > 1500 - void __cpuidex(int CPUInfo[4], int info_type, int ecxvalue); - #pragma intrinsic(__cpuidex) - #define CPUID(type, eax_, ebx_, ecx_, edx_) do { \ - int regs[4]; \ - __cpuidex(regs, type, 0); \ - eax_ = regs[0], ebx_ = regs[1], ecx_ = regs[2], edx_ = regs[3]; \ - } while(0) - #elif defined _M_X64 && defined _MSC_VER - void __cpuidex(int CPUInfo[4], int info_type); - #pragma intrinsic(__cpuidex) - #define CPUID(type, eax_, ebx_, ecx_, edx_) do { \ - int regs[4]; \ - __cpuidex(regs, type); \ - eax_ = regs[0], ebx_ = regs[1], ecx_ = regs[2], edx_ = regs[3]; \ - } while(0) - #elif defined _M_IX86 && defined _MSC_VER - #define CPUID(type, eax_, ebx_, ecx_, edx_) \ - __asm pushad \ - __asm mov eax, type \ - __asm xor ecx, ecx \ - __asm cpuid \ - __asm mov eax_, eax \ - __asm mov ebx_, ebx \ - __asm mov ecx_, ecx \ - __asm mov edx_, edx \ - __asm popad - #endif -#endif - - - -#if WITH_CR32S && WITH_CR32 - static bool cpu_has_simd32(void) - { - #if defined __x86_64__ || defined _M_X64 - return true; - #elif defined __i386__ || defined _M_IX86 - enum {SSE = 1 << 25, SSE2 = 1 << 26}; - unsigned eax_, ebx_, ecx_, edx_; - CPUID(1, eax_, ebx_, ecx_, edx_); - return (edx_ & (SSE|SSE2)) != 0; - #elif defined AV_CPU_FLAG_NEON - return !!(av_get_cpu_flags() & AV_CPU_FLAG_NEON); - #else - return false; - #endif - } - - static bool should_use_simd32(void) - { - char const * e; - return ((e = getenv("SOXR_USE_SIMD" )))? !!atoi(e) : - ((e = getenv("SOXR_USE_SIMD32")))? !!atoi(e) : cpu_has_simd32(); - } -#else - #define should_use_simd32() true -#endif - - - -#if WITH_CR64S && WITH_CR64 - #if defined __GNUC__ - #define XGETBV(type, eax_, edx_) \ - __asm__ __volatile__ ( \ - ".byte 0x0f, 0x01, 0xd0\n" \ - : "=a"(eax_), "=d"(edx_) : "c" (type)); - #elif defined _M_X64 && defined _MSC_FULL_VER && _MSC_FULL_VER >= 160040219 - #include - #define XGETBV(type, eax_, edx_) do { \ - union {uint64_t x; uint32_t y[2];} a = {_xgetbv(0)}; \ - eax_ = a.y[0], edx_ = a.y[1]; \ - } while(0) - #elif defined _M_IX86 && defined _MSC_VER - #define XGETBV(type, eax_, edx_) \ - __asm pushad \ - __asm mov ecx, type \ - __asm _emit 0x0f \ - __asm _emit 0x01 \ - __asm _emit 0xd0 \ - __asm mov eax_, eax \ - __asm mov edx_, edx \ - __asm popad - #else - #define XGETBV(type, eax_, edx_) eax_ = edx_ = 0 - #endif - - static bool cpu_has_simd64(void) - { - enum {OSXSAVE = 1 << 27, AVX = 1 << 28}; - unsigned eax_, ebx_, ecx_, edx_; - CPUID(1, eax_, ebx_, ecx_, edx_); - if ((ecx_ & (OSXSAVE|AVX)) == (OSXSAVE|AVX)) { - XGETBV(0, eax_, edx_); - return (eax_ & 6) == 6; - } - return false; - } - - static bool should_use_simd64(void) - { - char const * e; - return ((e = getenv("SOXR_USE_SIMD" )))? !!atoi(e) : - ((e = getenv("SOXR_USE_SIMD64")))? !!atoi(e) : cpu_has_simd64(); - } -#else - #define should_use_simd64() true -#endif - - - -extern control_block_t - _soxr_rate32_cb, - _soxr_rate32s_cb, - _soxr_rate64_cb, - _soxr_rate64s_cb, - _soxr_vr32_cb; - - - -static void runtime_num(char const * env_name, - int min, int max, unsigned * field) -{ - char const * e = getenv(env_name); - if (e) { - int i = atoi(e); - if (i >= min && i <= max) - *field = (unsigned)i; - } -} - - - -static void runtime_flag(char const * env_name, - unsigned n_bits, unsigned n_shift, unsigned long * flags) -{ - char const * e = getenv(env_name); - if (e) { - int i = atoi(e); - unsigned long mask = (1UL << n_bits) - 1; - if (i >= 0 && i <= (int)mask) - *flags &= ~(mask << n_shift), *flags |= ((unsigned long)i << n_shift); - } -} - - - -soxr_t soxr_create( - double input_rate, double output_rate, - unsigned num_channels, - soxr_error_t * error0, - soxr_io_spec_t const * io_spec, - soxr_quality_spec_t const * q_spec, - soxr_runtime_spec_t const * runtime_spec) -{ - double io_ratio = output_rate!=0? input_rate!=0? - input_rate / output_rate : -1 : input_rate!=0? -1 : 0; - static const float datatype_full_scale[] = {1, 1, 65536.*32768, 32768}; - soxr_t p = 0; - soxr_error_t error = 0; - -#if WITH_DEV_TRACE -#define _(x) (char)(sizeof(x)>=10? 'a'+(char)(sizeof(x)-10):'0'+(char)sizeof(x)) - char const * e = getenv("SOXR_TRACE"); - _soxr_trace_level = e? atoi(e) : 0; - { - static char const arch[] = {_(char), _(short), _(int), _(long), _(long long) - , ' ', _(float), _(double), _(long double) - , ' ', _(int *), _(int (*)(int)) - , ' ', HAVE_BIGENDIAN ? 'B' : 'L' -#if defined _OPENMP - , ' ', 'O', 'M', 'P' -#endif - , 0}; -#undef _ - lsx_debug("arch: %s", arch); - } -#endif - - if (q_spec && q_spec->e) error = q_spec->e; - else if (io_spec && (io_spec->itype | io_spec->otype) >= SOXR_SPLIT * 2) - error = "invalid io datatype(s)"; - - if (!error && !(p = calloc(sizeof(*p), 1))) error = "malloc failed"; - - if (p) { - control_block_t * control_block; - - p->q_spec = q_spec? *q_spec : soxr_quality_spec(SOXR_HQ, 0); - - if (q_spec) { /* Backwards compatibility with original API: */ - if (p->q_spec.passband_end > 2) - p->q_spec.passband_end /= 100; - if (p->q_spec.stopband_begin > 2) - p->q_spec.stopband_begin = 2 - p->q_spec.stopband_begin / 100; - } - - p->io_ratio = io_ratio; - p->num_channels = num_channels; - if (io_spec) - p->io_spec = *io_spec; - else - p->io_spec.scale = 1; - - p->runtime_spec = runtime_spec? *runtime_spec : soxr_runtime_spec(1); - - runtime_num("SOXR_MIN_DFT_SIZE", 8, 15, &p->runtime_spec.log2_min_dft_size); - runtime_num("SOXR_LARGE_DFT_SIZE", 8, 20, &p->runtime_spec.log2_large_dft_size); - runtime_num("SOXR_COEFS_SIZE", 100, 800, &p->runtime_spec.coef_size_kbytes); - runtime_num("SOXR_NUM_THREADS", 0, 64, &p->runtime_spec.num_threads); - runtime_flag("SOXR_COEF_INTERP", 2, 0, &p->runtime_spec.flags); - - runtime_flag("SOXR_STRICT_BUF", 1, 2, &p->runtime_spec.flags); - runtime_flag("SOXR_NOSMALLINTOPT", 1, 3, &p->runtime_spec.flags); - - p->io_spec.scale *= datatype_full_scale[p->io_spec.otype & 3] / - datatype_full_scale[p->io_spec.itype & 3]; - - p->seed = (unsigned long)time(0) ^ (unsigned long)(size_t)p; - -#if WITH_CR32 || WITH_CR32S || WITH_VR32 - if (0 -#if WITH_VR32 - || ((!WITH_CR32 && !WITH_CR32S) || (p->q_spec.flags & SOXR_VR)) -#endif -#if WITH_CR32 || WITH_CR32S - || !(WITH_CR64 || WITH_CR64S) || (p->q_spec.precision <= 20 && !(p->q_spec.flags & SOXR_DOUBLE_PRECISION)) -#endif - ) { - p->deinterleave = (deinterleave_t)_soxr_deinterleave_f; - p->interleave = (interleave_t)_soxr_interleave_f; - control_block = -#if WITH_VR32 - ((!WITH_CR32 && !WITH_CR32S) || (p->q_spec.flags & SOXR_VR))? &_soxr_vr32_cb : -#endif -#if WITH_CR32S - !WITH_CR32 || should_use_simd32()? &_soxr_rate32s_cb : -#endif - &_soxr_rate32_cb; - } -#if WITH_CR64 || WITH_CR64S - else -#endif -#endif -#if WITH_CR64 || WITH_CR64S - { - p->deinterleave = (deinterleave_t)_soxr_deinterleave; - p->interleave = (interleave_t)_soxr_interleave; - control_block = -#if WITH_CR64S - !WITH_CR64 || should_use_simd64()? &_soxr_rate64s_cb : -#endif - &_soxr_rate64_cb; - } -#endif - memcpy(&p->control_block, control_block, sizeof(p->control_block)); - - if (p->num_channels && io_ratio!=0) - error = soxr_set_io_ratio(p, io_ratio, 0); - } - if (error) - soxr_delete(p), p = 0; - if (error0) - *error0 = error; - return p; -} - - - -soxr_error_t soxr_set_input_fn(soxr_t p, - soxr_input_fn_t input_fn, void * input_fn_state, size_t max_ilen) -{ - p->input_fn_state = input_fn_state; - p->input_fn = input_fn; - p->max_ilen = max_ilen? max_ilen : (size_t)-1; - return 0; -} - - - -static void soxr_delete0(soxr_t p) -{ - unsigned i; - - if (p->resamplers) for (i = 0; i < p->num_channels; ++i) { - if (p->resamplers[i]) - resampler_close(p->resamplers[i]); - free(p->resamplers[i]); - } - free(p->resamplers); - free(p->channel_ptrs); - free(p->shared); - - memset(p, 0, sizeof(*p)); -} - - - -double soxr_delay(soxr_t p) -{ - return - (p && !p->error && p->resamplers)? resampler_delay(p->resamplers[0]) : 0; -} - - - -static soxr_error_t fatal_error(soxr_t p, soxr_error_t error) -{ - soxr_delete0(p); - return p->error = error; -} - - - -static soxr_error_t initialise(soxr_t p) -{ - unsigned i; - size_t shared_size, channel_size; - - resampler_sizes(&shared_size, &channel_size); - p->channel_ptrs = calloc(sizeof(*p->channel_ptrs), p->num_channels); - p->shared = calloc(shared_size, 1); - p->resamplers = calloc(sizeof(*p->resamplers), p->num_channels); - if (!p->shared || !p->channel_ptrs || !p->resamplers) - return fatal_error(p, "malloc failed"); - - for (i = 0; i < p->num_channels; ++i) { - soxr_error_t error; - if (!(p->resamplers[i] = calloc(channel_size, 1))) - return fatal_error(p, "malloc failed"); - error = resampler_create( - p->resamplers[i], - p->shared, - p->io_ratio, - &p->q_spec, - &p->runtime_spec, - p->io_spec.scale); - if (error) - return fatal_error(p, error); - } - return 0; -} - - - -soxr_error_t soxr_set_num_channels(soxr_t p, unsigned num_channels) -{ - if (!p) return "invalid soxr_t pointer"; - if (num_channels == p->num_channels) return p->error; - if (!num_channels) return "invalid # of channels"; - if (p->resamplers) return "# of channels can't be changed"; - p->num_channels = num_channels; - return soxr_set_io_ratio(p, p->io_ratio, 0); -} - - - -soxr_error_t soxr_set_io_ratio(soxr_t p, double io_ratio, size_t slew_len) -{ - unsigned i; - soxr_error_t error; - if (!p) return "invalid soxr_t pointer"; - if ((error = p->error)) return error; - if (!p->num_channels) return "must set # channels before O/I ratio"; - if (io_ratio <= 0) return "I/O ratio out-of-range"; - if (!p->channel_ptrs) { - p->io_ratio = io_ratio; - return initialise(p); - } - if (p->control_block[8]) { - for (i = 0; !error && i < p->num_channels; ++i) - resampler_set_io_ratio(p->resamplers[i], io_ratio, slew_len); - return error; - } - return fabs(p->io_ratio - io_ratio) < 1e-15? 0 : - "varying O/I ratio is not supported with this quality level"; -} - - - -void soxr_delete(soxr_t p) -{ - if (p) - soxr_delete0(p), free(p); -} - - - -soxr_error_t soxr_clear(soxr_t p) /* TODO: this, properly. */ -{ - if (p) { - struct soxr tmp = *p; - soxr_delete0(p); - memset(p, 0, sizeof(*p)); - p->input_fn = tmp.input_fn; - p->runtime_spec = tmp.runtime_spec; - p->q_spec = tmp.q_spec; - p->io_spec = tmp.io_spec; - p->num_channels = tmp.num_channels; - p->input_fn_state = tmp.input_fn_state; - memcpy(p->control_block, tmp.control_block, sizeof(p->control_block)); - p->deinterleave = tmp.deinterleave; - p->interleave = tmp.interleave; - return (p->q_spec.flags & RESET_ON_CLEAR)? - soxr_set_io_ratio(p, tmp.io_ratio, 0) : 0; - } - return "invalid soxr_t pointer"; -} - - - -static void soxr_input_1ch(soxr_t p, unsigned i, soxr_cbuf_t src, size_t len) -{ - sample_t * dest = resampler_input(p->resamplers[i], NULL, len); - (*p->deinterleave)(&dest, p->io_spec.itype, &src, len, 1); -} - - - -static size_t soxr_input(soxr_t p, void const * in, size_t len) -{ - bool separated = !!(p->io_spec.itype & SOXR_SPLIT); - unsigned i; - if (!p || p->error) return 0; - if (!in && len) {p->error = "null input buffer pointer"; return 0;} - if (!len) { - p->flushing = true; - return 0; - } - if (separated) - for (i = 0; i < p->num_channels; ++i) - soxr_input_1ch(p, i, ((soxr_cbufs_t)in)[i], len); - else { - for (i = 0; i < p->num_channels; ++i) - p->channel_ptrs[i] = resampler_input(p->resamplers[i], NULL, len); - (*p->deinterleave)( - (sample_t **)p->channel_ptrs, p->io_spec.itype, &in, len, p->num_channels); - } - return len; -} - - - -static size_t soxr_output_1ch(soxr_t p, unsigned i, soxr_buf_t dest, size_t len, bool separated) -{ - sample_t const * src; - if (p->flushing) - resampler_flush(p->resamplers[i]); - resampler_process(p->resamplers[i], len); - src = resampler_output(p->resamplers[i], NULL, &len); - if (separated) - p->clips += (p->interleave)(p->io_spec.otype, &dest, &src, - len, 1, (p->io_spec.flags & SOXR_NO_DITHER)? 0 : &p->seed); - else p->channel_ptrs[i] = (void /* const */ *)src; - return len; -} - - - -static size_t soxr_output_no_callback(soxr_t p, soxr_buf_t out, size_t len) -{ - unsigned u; - size_t done = 0; - bool separated = !!(p->io_spec.otype & SOXR_SPLIT); -#if defined _OPENMP - int i; - if (!p->runtime_spec.num_threads && p->num_channels > 1) -#pragma omp parallel for - for (i = 0; i < (int)p->num_channels; ++i) { - size_t done1; - done1 = soxr_output_1ch(p, (unsigned)i, ((soxr_bufs_t)out)[i], len, separated); - if (!i) - done = done1; - } else -#endif - for (u = 0; u < p->num_channels; ++u) - done = soxr_output_1ch(p, u, ((soxr_bufs_t)out)[u], len, separated); - - if (!separated) - p->clips += (p->interleave)(p->io_spec.otype, &out, (sample_t const * const *)p->channel_ptrs, - done, p->num_channels, (p->io_spec.flags & SOXR_NO_DITHER)? 0 : &p->seed); - return done; -} - - - -size_t soxr_output(soxr_t p, void * out, size_t len0) -{ - size_t odone, odone0 = 0, olen = len0, osize, idone; - size_t ilen = min(p->max_ilen, (size_t)ceil((double)olen *p->io_ratio)); - void const * in = out; /* Set to !=0, so that caller may leave unset. */ - bool was_flushing; - - if (!p || p->error) return 0; - if (!out && len0) {p->error = "null output buffer pointer"; return 0;} - - do { - odone = soxr_output_no_callback(p, out, olen); - odone0 += odone; - if (odone0 == len0 || !p->input_fn || p->flushing) - break; - - osize = soxr_datatype_size(p->io_spec.otype) * p->num_channels; - out = (char *)out + osize * odone; - olen -= odone; - idone = p->input_fn(p->input_fn_state, &in, ilen); - was_flushing = p->flushing; - if (!in) - p->error = "input function reported failure"; - else soxr_input(p, in, idone); - } while (odone || idone || (!was_flushing && p->flushing)); - return odone0; -} - - - -static size_t soxr_i_for_o(soxr_t p, size_t olen, size_t ilen) -{ - size_t result; -#if 0 - if (p->runtime_spec.flags & SOXR_STRICT_BUFFERING) - result = rate_i_for_o(p->resamplers[0], olen); - else -#endif - result = (size_t)ceil((double)olen * p->io_ratio); - return min(result, ilen); -} - - - -#if 0 -static size_t soxr_o_for_i(soxr_t p, size_t ilen, size_t olen) -{ - size_t result = (size_t)ceil((double)ilen / p->io_ratio); - return min(result, olen); -} -#endif - - - -soxr_error_t soxr_process(soxr_t p, - void const * in , size_t ilen0, size_t * idone0, - void * out, size_t olen , size_t * odone0) -{ - size_t ilen, idone, odone = 0; - unsigned u; - bool flush_requested = false; - - if (!p) return "null pointer"; - - if (!in) - flush_requested = true, ilen = ilen0 = 0; - else { - if ((ptrdiff_t)ilen0 < 0) - flush_requested = true, ilen0 = ~ilen0; - if (idone0 && (1 || flush_requested)) - ilen = soxr_i_for_o(p, olen, ilen0); - else - ilen = ilen0/*, olen = soxr_o_for_i(p, ilen, olen)*/; - } - p->flushing |= ilen == ilen0 && flush_requested; - - if (!out && !in) - idone = ilen; - else if (p->io_spec.itype & p->io_spec.otype & SOXR_SPLIT) { /* Both i & o */ -#if defined _OPENMP - int i; - if (!p->runtime_spec.num_threads && p->num_channels > 1) -#pragma omp parallel for - for (i = 0; i < (int)p->num_channels; ++i) { - size_t done; - if (in) - soxr_input_1ch(p, (unsigned)i, ((soxr_cbufs_t)in)[i], ilen); - done = soxr_output_1ch(p, (unsigned)i, ((soxr_bufs_t)out)[i], olen, true); - if (!i) - odone = done; - } else -#endif - for (u = 0; u < p->num_channels; ++u) { - if (in) - soxr_input_1ch(p, u, ((soxr_cbufs_t)in)[u], ilen); - odone = soxr_output_1ch(p, u, ((soxr_bufs_t)out)[u], olen, true); - } - idone = ilen; - } - else { - idone = ilen? soxr_input (p, in , ilen) : 0; - odone = soxr_output(p, out, olen); - } - if (idone0) *idone0 = idone; - if (odone0) *odone0 = odone; - return p->error; -} - - - -soxr_error_t soxr_oneshot( - double irate, double orate, - unsigned num_channels, - void const * in , size_t ilen, size_t * idone, - void * out, size_t olen, size_t * odone, - soxr_io_spec_t const * io_spec, - soxr_quality_spec_t const * q_spec, - soxr_runtime_spec_t const * runtime_spec) -{ - soxr_t resampler; - soxr_error_t error = q_spec? q_spec->e : 0; - if (!error) { - soxr_quality_spec_t q_spec1; - if (!q_spec) - q_spec1 = soxr_quality_spec(SOXR_LQ, 0), q_spec = &q_spec1; - resampler = soxr_create(irate, orate, num_channels, - &error, io_spec, q_spec, runtime_spec); - } - if (!error) { - error = soxr_process(resampler, in, ~ilen, idone, out, olen, odone); - soxr_delete(resampler); - } - return error; -} - - - -soxr_error_t soxr_set_error(soxr_t p, soxr_error_t error) -{ - if (!p) return "null pointer"; - if (!p->error && p->error != error) return p->error; - p->error = error; - return 0; -} diff --git a/C/src/soxr-0.1.3/src/soxr.h b/C/src/soxr-0.1.3/src/soxr.h deleted file mode 100644 index 09ec7c46..00000000 --- a/C/src/soxr-0.1.3/src/soxr.h +++ /dev/null @@ -1,344 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-18 robs@users.sourceforge.net - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - - - -/* -------------------------------- Gubbins --------------------------------- */ - -#if !defined soxr_included -#define soxr_included - - -#if defined __cplusplus - #include - extern "C" { -#else - #include -#endif - -#if defined SOXR_DLL - #if defined soxr_EXPORTS - #define SOXR __declspec(dllexport) - #else - #define SOXR __declspec(dllimport) - #endif -#elif defined SOXR_VISIBILITY && defined __GNUC__ && (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 1) - #define SOXR __attribute__ ((visibility("default"))) -#else - #define SOXR -#endif - -typedef struct soxr_io_spec soxr_io_spec_t; -typedef struct soxr_quality_spec soxr_quality_spec_t; -typedef struct soxr_runtime_spec soxr_runtime_spec_t; - - - -/* ---------------------------- API conventions -------------------------------- - -Buffer lengths (and occupancies) are expressed as the number of contained -samples per channel. - -Parameter names for buffer lengths have the suffix `len'. - -A single-character `i' or 'o' is often used in names to give context as -input or output (e.g. ilen, olen). */ - - - -/* --------------------------- Version management --------------------------- */ - -/* E.g. #if SOXR_THIS_VERSION >= SOXR_VERSION(0,1,1) ... */ - -#define SOXR_VERSION(x,y,z) (((x)<<16)|((y)<<8)|(z)) -#define SOXR_THIS_VERSION SOXR_VERSION(0,1,3) -#define SOXR_THIS_VERSION_STR "0.1.3" - - - -/* --------------------------- Type declarations ---------------------------- */ - -typedef struct soxr * soxr_t; /* A resampler for 1 or more channels. */ -typedef char const * soxr_error_t; /* 0:no-error; non-0:error. */ - -typedef void * soxr_buf_t; /* 1 buffer of channel-interleaved samples. */ -typedef void const * soxr_cbuf_t; /* Ditto; read-only. */ - -typedef soxr_buf_t const * soxr_bufs_t;/* Or, a separate buffer for each ch. */ -typedef soxr_cbuf_t const * soxr_cbufs_t; /* Ditto; read-only. */ - -typedef void const * soxr_in_t; /* Either a soxr_cbuf_t or soxr_cbufs_t, - depending on itype in soxr_io_spec_t. */ -typedef void * soxr_out_t; /* Either a soxr_buf_t or soxr_bufs_t, - depending on otype in soxr_io_spec_t. */ - - - -/* --------------------------- API main functions --------------------------- */ - -SOXR char const * soxr_version(void); /* Query library version: "libsoxr-x.y.z" */ - -#define soxr_strerror(e) /* Soxr counterpart to strerror. */ \ - ((e)?(e):"no error") - - -/* Create a stream resampler: */ - -SOXR soxr_t soxr_create( - double input_rate, /* Input sample-rate. */ - double output_rate, /* Output sample-rate. */ - unsigned num_channels, /* Number of channels to be used. */ - /* All following arguments are optional (may be set to NULL). */ - soxr_error_t *, /* To report any error during creation. */ - soxr_io_spec_t const *, /* To specify non-default I/O formats. */ - soxr_quality_spec_t const *, /* To specify non-default resampling quality.*/ - soxr_runtime_spec_t const *);/* To specify non-default runtime resources. - - Default io_spec is per soxr_io_spec(SOXR_FLOAT32_I, SOXR_FLOAT32_I) - Default quality_spec is per soxr_quality_spec(SOXR_HQ, 0) - Default runtime_spec is per soxr_runtime_spec(1) */ - - - -/* If not using an app-supplied input function, after creating a stream - * resampler, repeatedly call: */ - -SOXR soxr_error_t soxr_process( - soxr_t resampler, /* As returned by soxr_create. */ - /* Input (to be resampled): */ - soxr_in_t in, /* Input buffer(s); may be NULL (see below). */ - size_t ilen, /* Input buf. length (samples per channel). */ - size_t * idone, /* To return actual # samples used (<= ilen). */ - /* Output (resampled): */ - soxr_out_t out, /* Output buffer(s).*/ - size_t olen, /* Output buf. length (samples per channel). */ - size_t * odone); /* To return actual # samples out (<= olen). - - Note that no special meaning is associated with ilen or olen equal to - zero. End-of-input (i.e. no data is available nor shall be available) - may be indicated by seting `in' to NULL. */ - - - -/* If using an app-supplied input function, it must look and behave like this:*/ - -typedef size_t /* data_len */ - (* soxr_input_fn_t)( /* Supply data to be resampled. */ - void * input_fn_state, /* As given to soxr_set_input_fn (below). */ - soxr_in_t * data, /* Returned data; see below. N.B. ptr to ptr(s)*/ - size_t requested_len); /* Samples per channel, >= returned data_len. - - data_len *data Indicates Meaning - ------- ------- ------------ ------------------------- - !=0 !=0 Success *data contains data to be - input to the resampler. - 0 !=0 (or End-of-input No data is available nor - not set) shall be available. - 0 0 Failure An error occurred whilst trying to - source data to be input to the resampler. */ - -/* and be registered with a previously created stream resampler using: */ - -SOXR soxr_error_t soxr_set_input_fn(/* Set (or reset) an input function.*/ - soxr_t resampler, /* As returned by soxr_create. */ - soxr_input_fn_t, /* Function to supply data to be resampled.*/ - void * input_fn_state, /* If needed by the input function. */ - size_t max_ilen); /* Maximum value for input fn. requested_len.*/ - -/* then repeatedly call: */ - -SOXR size_t /*odone*/ soxr_output(/* Resample and output a block of data.*/ - soxr_t resampler, /* As returned by soxr_create. */ - soxr_out_t data, /* App-supplied buffer(s) for resampled data.*/ - size_t olen); /* Amount of data to output; >= odone. */ - - - -/* Common stream resampler operations: */ - -SOXR soxr_error_t soxr_error(soxr_t); /* Query error status. */ -SOXR size_t * soxr_num_clips(soxr_t); /* Query int. clip counter (for R/W). */ -SOXR double soxr_delay(soxr_t); /* Query current delay in output samples.*/ -SOXR char const * soxr_engine(soxr_t); /* Query resampling engine name. */ - -SOXR soxr_error_t soxr_clear(soxr_t); /* Ready for fresh signal, same config. */ -SOXR void soxr_delete(soxr_t); /* Free resources. */ - - - -/* `Short-cut', single call to resample a (probably short) signal held entirely - * in memory. See soxr_create and soxr_process above for parameter details. - * Note that unlike soxr_create however, the default quality spec. for - * soxr_oneshot is per soxr_quality_spec(SOXR_LQ, 0). */ - -SOXR soxr_error_t soxr_oneshot( - double input_rate, - double output_rate, - unsigned num_channels, - soxr_in_t in , size_t ilen, size_t * idone, - soxr_out_t out, size_t olen, size_t * odone, - soxr_io_spec_t const *, - soxr_quality_spec_t const *, - soxr_runtime_spec_t const *); - - - -/* For variable-rate resampling. See example # 5 for how to create a - * variable-rate resampler and how to use this function. */ - -SOXR soxr_error_t soxr_set_io_ratio(soxr_t, double io_ratio, size_t slew_len); - - - -/* -------------------------- API type definitions -------------------------- */ - -typedef enum { /* Datatypes supported for I/O to/from the resampler: */ - /* Internal; do not use: */ - SOXR_FLOAT32, SOXR_FLOAT64, SOXR_INT32, SOXR_INT16, SOXR_SPLIT = 4, - - /* Use for interleaved channels: */ - SOXR_FLOAT32_I = SOXR_FLOAT32, SOXR_FLOAT64_I, SOXR_INT32_I, SOXR_INT16_I, - - /* Use for split channels: */ - SOXR_FLOAT32_S = SOXR_SPLIT , SOXR_FLOAT64_S, SOXR_INT32_S, SOXR_INT16_S - -} soxr_datatype_t; - -#define soxr_datatype_size(x) /* Returns `sizeof' a soxr_datatype_t sample. */\ - ((unsigned char *)"\4\10\4\2")[(x)&3] - - - -struct soxr_io_spec { /* Typically */ - soxr_datatype_t itype; /* Input datatype. SOXR_FLOAT32_I */ - soxr_datatype_t otype; /* Output datatype. SOXR_FLOAT32_I */ - double scale; /* Linear gain to apply during resampling. 1 */ - void * e; /* Reserved for internal use 0 */ - unsigned long flags; /* Per the following #defines. 0 */ -}; - -#define SOXR_TPDF 0 /* Applicable only if otype is INT16. */ -#define SOXR_NO_DITHER 8u /* Disable the above. */ - - - -struct soxr_quality_spec { /* Typically */ - double precision; /* Conversion precision (in bits). 20 */ - double phase_response; /* 0=minimum, ... 50=linear, ... 100=maximum 50 */ - double passband_end; /* 0dB pt. bandwidth to preserve; nyquist=1 0.913*/ - double stopband_begin; /* Aliasing/imaging control; > passband_end 1 */ - void * e; /* Reserved for internal use. 0 */ - unsigned long flags; /* Per the following #defines. 0 */ -}; - -#define SOXR_ROLLOFF_SMALL 0u /* <= 0.01 dB */ -#define SOXR_ROLLOFF_MEDIUM 1u /* <= 0.35 dB */ -#define SOXR_ROLLOFF_NONE 2u /* For Chebyshev bandwidth. */ - -#define SOXR_HI_PREC_CLOCK 8u /* Increase `irrational' ratio accuracy. */ -#define SOXR_DOUBLE_PRECISION 16u /* Use D.P. calcs even if precision <= 20. */ -#define SOXR_VR 32u /* Variable-rate resampling. */ - - - -struct soxr_runtime_spec { /* Typically */ - unsigned log2_min_dft_size; /* For DFT efficiency. [8,15] 10 */ - unsigned log2_large_dft_size; /* For DFT efficiency. [8,20] 17 */ - unsigned coef_size_kbytes; /* For SOXR_COEF_INTERP_AUTO (below). 400 */ - unsigned num_threads; /* 0: per OMP_NUM_THREADS; 1: 1 thread. 1 */ - void * e; /* Reserved for internal use. 0 */ - unsigned long flags; /* Per the following #defines. 0 */ -}; - /* For `irrational' ratios only: */ -#define SOXR_COEF_INTERP_AUTO 0u /* Auto select coef. interpolation. */ -#define SOXR_COEF_INTERP_LOW 2u /* Man. select: less CPU, more memory. */ -#define SOXR_COEF_INTERP_HIGH 3u /* Man. select: more CPU, less memory. */ - - - -/* -------------------------- API type constructors ------------------------- */ - -/* These functions allow setting of the most commonly-used structure - * parameters, with other parameters being given default values. The default - * values may then be overridden, directly in the structure, if needed. */ - -SOXR soxr_quality_spec_t soxr_quality_spec( - unsigned long recipe, /* Per the #defines immediately below. */ - unsigned long flags); /* As soxr_quality_spec_t.flags. */ - - /* The 5 standard qualities found in SoX: */ -#define SOXR_QQ 0 /* 'Quick' cubic interpolation. */ -#define SOXR_LQ 1 /* 'Low' 16-bit with larger rolloff. */ -#define SOXR_MQ 2 /* 'Medium' 16-bit with medium rolloff. */ -#define SOXR_HQ SOXR_20_BITQ /* 'High quality'. */ -#define SOXR_VHQ SOXR_28_BITQ /* 'Very high quality'. */ - -#define SOXR_16_BITQ 3 -#define SOXR_20_BITQ 4 -#define SOXR_24_BITQ 5 -#define SOXR_28_BITQ 6 -#define SOXR_32_BITQ 7 - /* Reserved for internal use (to be removed): */ -#define SOXR_LSR0Q 8 /* 'Best sinc'. */ -#define SOXR_LSR1Q 9 /* 'Medium sinc'. */ -#define SOXR_LSR2Q 10 /* 'Fast sinc'. */ - -#define SOXR_LINEAR_PHASE 0x00 -#define SOXR_INTERMEDIATE_PHASE 0x10 -#define SOXR_MINIMUM_PHASE 0x30 - -#define SOXR_STEEP_FILTER 0x40 - - - -SOXR soxr_runtime_spec_t soxr_runtime_spec( - unsigned num_threads); - - - -SOXR soxr_io_spec_t soxr_io_spec( - soxr_datatype_t itype, - soxr_datatype_t otype); - - - -/* --------------------------- Advanced use only ---------------------------- */ - -/* For new designs, the following functions/usage will probably not be needed. - * They might be useful when adding soxr into an existing design where values - * for the resampling-rate and/or number-of-channels parameters to soxr_create - * are not available when that function will be called. In such cases, the - * relevant soxr_create parameter(s) can be given as 0, then one or both of the - * following (as appropriate) later invoked (but prior to calling soxr_process - * or soxr_output): - * - * soxr_set_error(soxr, soxr_set_io_ratio(soxr, io_ratio, 0)); - * soxr_set_error(soxr, soxr_set_num_channels(soxr, num_channels)); - */ - -SOXR soxr_error_t soxr_set_error(soxr_t, soxr_error_t); -SOXR soxr_error_t soxr_set_num_channels(soxr_t, unsigned); - - - -#undef SOXR - -#if defined __cplusplus -} -#endif - -#endif diff --git a/C/src/soxr-0.1.3/src/soxr.pc.in b/C/src/soxr-0.1.3/src/soxr.pc.in deleted file mode 100644 index 69d225b2..00000000 --- a/C/src/soxr-0.1.3/src/soxr.pc.in +++ /dev/null @@ -1,5 +0,0 @@ -Name: ${PROJECT_NAME} -Description: ${DESCRIPTION_SUMMARY} -Version: ${PROJECT_VERSION} -Libs: -L${LIB_INSTALL_DIR} -l${PROJECT_NAME} -Cflags: -I${INCLUDE_INSTALL_DIR} diff --git a/C/src/soxr-0.1.3/src/std-types.h b/C/src/soxr-0.1.3/src/std-types.h deleted file mode 100644 index c5e8636a..00000000 --- a/C/src/soxr-0.1.3/src/std-types.h +++ /dev/null @@ -1,48 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#if !defined soxr_std_types_included -#define soxr_std_types_included - -#include "soxr-config.h" - -#include - -#if HAVE_STDBOOL_H - #include -#else - #undef bool - #undef false - #undef true - #define bool int - #define false 0 - #define true 1 -#endif - -#if HAVE_STDINT_H - #include -#else - #undef int16_t - #undef int32_t - #undef int64_t - #undef uint32_t - #undef uint64_t - #define int16_t short - #if LONG_MAX > 2147483647L - #define int32_t int - #define int64_t long - #elif LONG_MAX < 2147483647L - #error this library requires that 'long int' has at least 32-bits - #else - #define int32_t long - #if defined _MSC_VER - #define int64_t __int64 - #else - #define int64_t long long - #endif - #endif - #define uint32_t unsigned int32_t - #define uint64_t unsigned int64_t -#endif - -#endif diff --git a/C/src/soxr-0.1.3/src/util-simd.c b/C/src/soxr-0.1.3/src/util-simd.c deleted file mode 100644 index ec548fde..00000000 --- a/C/src/soxr-0.1.3/src/util-simd.c +++ /dev/null @@ -1,89 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#include -#include -#include - -#include "soxr-config.h" - -#define SIMD_ALIGNMENT (sizeof(float) * (1 + (PFFFT_DOUBLE|AVCODEC_FOUND)) * 4) - -void * SIMD_ALIGNED_MALLOC(size_t size) -{ - char * p1 = 0, * p = malloc(size + SIMD_ALIGNMENT); - if (p) { - p1 = (char *)((size_t)(p + SIMD_ALIGNMENT) & ~(SIMD_ALIGNMENT - 1)); - *((void * *)p1 - 1) = p; - } - return p1; -} - - - -void * SIMD_ALIGNED_CALLOC(size_t nmemb, size_t size) -{ - void * p = SIMD_ALIGNED_MALLOC(nmemb * size); - if (p) - memset(p, 0, nmemb * size); - return p; -} - - - -void SIMD_ALIGNED_FREE(void * p1) -{ - if (p1) - free(*((void * *)p1 - 1)); -} - - - -#define PFFT_MACROS_ONLY -#include "pffft.c" - - - -void ORDERED_CONVOLVE_SIMD(int n, void * not_used, float * a, float const * b) -{ - int i; - float ab0, ab1; - v4sf * RESTRICT va = (v4sf *)a; - v4sf const * RESTRICT vb = (v4sf const *)b; - assert(VALIGNED(a) && VALIGNED(b)); - ab0 = a[0] * b[0], ab1 = a[1] * b[1]; - for (i = 0; i < n / 4; i += 2) { - v4sf a1r = va[i+0], a1i = va[i+1]; - v4sf b1r = vb[i+0], b1i = vb[i+1]; - UNINTERLEAVE2(a1r, a1i, a1r, a1i); - UNINTERLEAVE2(b1r, b1i, b1r, b1i); - VCPLXMUL(a1r, a1i, b1r, b1i); - INTERLEAVE2(a1r, a1i, a1r, a1i); - va[i+0] = a1r, va[i+1] = a1i; - } - a[0] = ab0, a[1] = ab1; - (void)not_used; -} - - - -void ORDERED_PARTIAL_CONVOLVE_SIMD(int n, float * a, float const * b) -{ - int i; - float ab0; - v4sf * RESTRICT va = (v4sf *)a; - v4sf const * RESTRICT vb = (v4sf const *)b; - assert(VALIGNED(a) && VALIGNED(b)); - ab0 = a[0] * b[0]; - for (i = 0; i < n / 4; i += 2) { - v4sf a1r = va[i+0], a1i = va[i+1]; - v4sf b1r = vb[i+0], b1i = vb[i+1]; - UNINTERLEAVE2(a1r, a1i, a1r, a1i); - UNINTERLEAVE2(b1r, b1i, b1r, b1i); - VCPLXMUL(a1r, a1i, b1r, b1i); - INTERLEAVE2(a1r, a1i, a1r, a1i); - va[i+0] = a1r, va[i+1] = a1i; - } - a[0] = ab0; - a[1] = b[n] * a[n] - b[n+1] * a[n+1]; -} diff --git a/C/src/soxr-0.1.3/src/util32s.c b/C/src/soxr-0.1.3/src/util32s.c deleted file mode 100644 index b9c9e08b..00000000 --- a/C/src/soxr-0.1.3/src/util32s.c +++ /dev/null @@ -1,8 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#define PFFFT_DOUBLE 0 - -#include "util32s.h" - -#include "util-simd.c" diff --git a/C/src/soxr-0.1.3/src/util32s.h b/C/src/soxr-0.1.3/src/util32s.h deleted file mode 100644 index 12226e50..00000000 --- a/C/src/soxr-0.1.3/src/util32s.h +++ /dev/null @@ -1,23 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#if !defined soxr_util32s_included -#define soxr_util32s_included - -#include - -void * _soxr_simd32_aligned_malloc(size_t); -void * _soxr_simd32_aligned_calloc(size_t, size_t); -void _soxr_simd32_aligned_free(void *); - -#define SIMD_ALIGNED_MALLOC _soxr_simd32_aligned_malloc -#define SIMD_ALIGNED_CALLOC _soxr_simd32_aligned_calloc -#define SIMD_ALIGNED_FREE _soxr_simd32_aligned_free - -void _soxr_ordered_convolve_simd32(int n, void * not_used, float * a, float const * b); -void _soxr_ordered_partial_convolve_simd32(int n, float * a, float const * b); - -#define ORDERED_CONVOLVE_SIMD _soxr_ordered_convolve_simd32 -#define ORDERED_PARTIAL_CONVOLVE_SIMD _soxr_ordered_partial_convolve_simd32 - -#endif diff --git a/C/src/soxr-0.1.3/src/util64s.c b/C/src/soxr-0.1.3/src/util64s.c deleted file mode 100644 index 0faa9e9e..00000000 --- a/C/src/soxr-0.1.3/src/util64s.c +++ /dev/null @@ -1,8 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#define PFFFT_DOUBLE 1 - -#include "util64s.h" - -#include "util-simd.c" diff --git a/C/src/soxr-0.1.3/src/util64s.h b/C/src/soxr-0.1.3/src/util64s.h deleted file mode 100644 index 7beeb899..00000000 --- a/C/src/soxr-0.1.3/src/util64s.h +++ /dev/null @@ -1,23 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#if !defined soxr_util64s_included -#define soxr_util64s_included - -#include - -void * _soxr_simd64_aligned_malloc(size_t); -void * _soxr_simd64_aligned_calloc(size_t, size_t); -void _soxr_simd64_aligned_free(void *); - -#define SIMD_ALIGNED_MALLOC _soxr_simd64_aligned_malloc -#define SIMD_ALIGNED_CALLOC _soxr_simd64_aligned_calloc -#define SIMD_ALIGNED_FREE _soxr_simd64_aligned_free - -void _soxr_ordered_convolve_simd64(int n, void * not_used, double * a, double const * b); -void _soxr_ordered_partial_convolve_simd64(int n, double * a, double const * b); - -#define ORDERED_CONVOLVE_SIMD _soxr_ordered_convolve_simd64 -#define ORDERED_PARTIAL_CONVOLVE_SIMD _soxr_ordered_partial_convolve_simd64 - -#endif diff --git a/C/src/soxr-0.1.3/src/vr-coefs.c b/C/src/soxr-0.1.3/src/vr-coefs.c deleted file mode 100644 index a57bec8c..00000000 --- a/C/src/soxr-0.1.3/src/vr-coefs.c +++ /dev/null @@ -1,115 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2013 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -/* Generate the filter coefficients for variable-rate resampling. */ - -#include -#include -#include -#define PI 3.14159265358979323846 /* Since M_PI can't be relied on */ - -static void print(double * h, int m, double l, char const * name) -{ /* Print out a filter: */ - int i, N = l? (int)(l*m)-(l>1) : m, R=(N+1)/2; - int a = !l||l>1? 0:N-R, b = l>1? R:N; - printf("static float const %s[] = {\n", name); - if (l>1) printf(" 0.f,"); else if (!l) l=1; - for (i=a; h && i 0 && x E[i] >= x E[i z 1]) -#define PEAK do {if (k0)-(E[i]<0);} while (0) - -typedef struct {double x, beta, gamma;} coef_t; - -static double amp_response(coef_t * coef, int R, double f, int i) -{ - double n = 0, d = 0, x = cos(PI*f), t; - for (; i < R; d += t = coef[i].beta / t, n += coef[i].gamma * t, ++i) - if (fabs(t = x - coef[i].x) < 1e-9) return coef[i].gamma; - return n/d; -} - -static void fir(int m, double l, double Fp0, double Fs0, - double weight0, int density, char const * name) -{ - double Fp=Fp0/l, Fs=Fs0/l, weight=1/weight0, inc[2], Ws=1-Fs; - int N = (int)(l*m)-(l>1), R=(N+1)/2, NP=R+1, grid_size=1+density*R+1, pass=0; - int n1 = Ws>=(2*R-1)*Fp? 1:(int)(R*Fp/(Fp+Ws)+.5), n2=NP-n1, _1, i, j, k; - int * peak = calloc(sizeof(*peak), (size_t)(NP+1)), * P=peak, end[2]; - coef_t * coef = calloc(sizeof(*coef), (size_t)(NP)); - float * E = calloc(sizeof(*E ), (size_t)(grid_size)); - double d, n, e, f, mult, delta, sum, hi, lo, * A = (double*)E, *h=0; - - if (!P || !coef || !E) goto END; - end[0] = n1 * density, end[1] = grid_size-1; /* Create prototype peaks: */ - inc[0] = Fp/end[0], inc[1] = n2==1? 0 : Ws / ((n2-1)*density); - for (i=0; iE[i+1]) || (EE(-,-) && E[i] 1) goto END; /* Too many/few? */ - P = peak + k * (fabs(E[peak[0]]) < fabs(E[peak[NP]])); /* rm 1st? */ - - for (lo = hi = fabs(E[P[0]]), i=1; ihi? e:hi; - } while ((hi-lo)/hi > .001 && ++pass < 20); - /* Create impulse response from final amp. resp. coefs: */ - if (!(h = malloc(sizeof(*h)*(size_t)N))) goto END; - for (i = 0; i < R; f = 2.*i/N, A[i++] = amp_response(coef,R,f,0)*even_adj(f)); - for (i = 0; i < R; h[N-1-i] = h[i] = sum/N, ++i) - for (sum=*A, j=1; j -#include "math-wrap.h" -#include -#include -#include "internal.h" -#define FIFO_SIZE_T int -#define FIFO_MIN 0x8000 -#include "fifo.h" -#include "vr-coefs.h" - -#define FADE_LEN_BITS 9 -#define PHASE_BITS_D 10 -#define PHASE_BITS_U 9 - -#define PHASES0_D 12 -#define POLY_FIR_LEN_D 20 -#define PHASES0_U 6 -#define POLY_FIR_LEN_U 12 - -#define MULT32 (65536. * 65536.) -#define PHASES_D (1 << PHASE_BITS_D) -#define PHASES_U (1 << PHASE_BITS_U) - -#define CONVOLVE \ - _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \ - _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ \ - _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - -#define HALF_FIR_LEN_2 (iAL(half_fir_coefs) - 1) -#define HALF_FIR_LEN_4 (HALF_FIR_LEN_2 / 2) - -#define _ sum += (input[-i] + input[i]) * half_fir_coefs[i], ++i; -static float half_fir(float const * input) -{ - long i = 1; - float sum = input[0] * half_fir_coefs[0]; - CONVOLVE CONVOLVE - assert(i == HALF_FIR_LEN_2 + 1); - return (float)sum; -} -#undef _ - -#define _ sum += (input[-i] + input[i]) * half_fir_coefs[2*i], ++i; -static float double_fir0(float const * input) -{ - int i = 1; - float sum = input[0] * half_fir_coefs[0]; - CONVOLVE - assert(i == HALF_FIR_LEN_4 + 1); - return (float)(sum * 2); -} -#undef _ - -#define _ sum += (input[-i] + input[1+i]) * half_fir_coefs[2*i+1], ++i; -static float double_fir1(float const * input) -{ - int i = 0; - float sum = 0; - CONVOLVE - assert(i == HALF_FIR_LEN_4 + 0); - return (float)(sum * 2); -} -#undef _ - -static float fast_half_fir(float const * input) -{ - int i = 0; - float sum = input[0] * .5f; -#define _ sum += (input[-(2*i+1)] + input[2*i+1]) * fast_half_fir_coefs[i], ++i; - _ _ _ _ _ _ -#undef _ - return (float)sum; -} - -#define IIR_FILTER _ _ _ _ _ _ _ -#define _ in1=(in1-p->y[i])*iir_coefs[i]+tmp1;tmp1=p->y[i],p->y[i]=in1;++i;\ - in0=(in0-p->y[i])*iir_coefs[i]+tmp0;tmp0=p->y[i],p->y[i]=in0;++i; - -typedef struct {float x[2], y[AL(iir_coefs)];} half_iir_t; - -static float half_iir1(half_iir_t * p, float in0, float in1) -{ - int i = 0; - float tmp0, tmp1; - tmp0 = p->x[0], p->x[0] = in0; - tmp1 = p->x[1], p->x[1] = in1; - IIR_FILTER - p->y[i] = in1 = (in1 - p->y[i]) * iir_coefs[i] + tmp1; - return in1 + in0; -} -#undef _ - -static void half_iir(half_iir_t * p, float * obuf, float const * ibuf, int olen) -{ - int i; - for (i=0; i < olen; obuf[i] = (float)half_iir1(p, ibuf[i*2], ibuf[i*2+1]),++i); -} - -static void half_phase(half_iir_t * p, float * buf, int len) -{ - float const small_normal = 1/MULT32/MULT32; /* To quash denormals on path 0.*/ - int i; - for (i = 0; i < len; buf[i] = (float)half_iir1(p, buf[i], 0), ++i); -#define _ p->y[i] += small_normal, i += 2; - i = 0, _ IIR_FILTER -#undef _ -#define _ p->y[i] -= small_normal, i += 2; - i = 0, _ IIR_FILTER -#undef _ -} - -#define coef(coef_p, interp_order, fir_len, phase_num, coef_interp_num, \ - fir_coef_num) coef_p[(fir_len) * ((interp_order) + 1) * (phase_num) + \ - ((interp_order) + 1) * (fir_coef_num) + (interp_order - coef_interp_num)] - -#define COEF(h,l,i) ((i)<0||(i)>=(l)?0:(h)[(i)>(l)/2?(l)-(i):(i)]) -static void prepare_coefs(float * coefs, int n, int phases0, int phases, - float const * coefs0, double multiplier) -{ - double k[6]; - int length0 = n * phases0, length = n * phases, K0 = iAL(k)/2 - 1, i, j, pos; - float * coefs1 = malloc(((size_t)length / 2 + 1) * sizeof(*coefs1)); - float * p = coefs1, f0, f1 = 0; - - for (j = 0; j < iAL(k); k[j] = COEF(coefs0, length0, j - K0), ++j); - for (pos = i = 0; i < length0 / 2; ++i) { - double b=(1/24.)*(k[0]+k[4]+6*k[2]-4*(k[1]+k[3])),d=.5*(k[1]+k[3])-k[2]-b; - double a=(1/120.)*(k[5]-k[2]-9*(9*b+d)+2.5*(k[3]-k[1])-2*(k[4]-k[0])); - double c=(1/12.)*(k[4]-k[0]-2*(k[3]-k[1])-60*a),e=.5*(k[3]-k[1])-a-c; - for (; pos / phases == i; pos += phases0) { - double x = (double)(pos % phases) / phases; - *p++ = (float)(k[K0] + ((((a*x + b)*x + c)*x + d)*x + e)*x); - } - for (j = 0; j < iAL(k) - 1; k[j] = k[j + 1], ++j); - k[j] = COEF(coefs0, length0, i + iAL(k) / 2 + 1); - } - if (!(length & 1)) - *p++ = (float)k[K0]; - assert(p - coefs1 == length / 2 + 1); - - for (i = 0; i < n; ++i) for (j = phases - 1; j >= 0; --j, f1 = f0) { - pos = (n - 1 - i) * phases + j; - f0 = COEF(coefs1, length, pos) * (float)multiplier; - coef(coefs, 1, n, j, 0, i) = (float)f0; - coef(coefs, 1, n, j, 1, i) = (float)(f1 - f0); - } - free(coefs1); -} - -#define _ sum += (b *x + a)*input[i], ++i; -#define a (coef(poly_fir_coefs_d, 1, POLY_FIR_LEN_D, phase, 0,i)) -#define b (coef(poly_fir_coefs_d, 1, POLY_FIR_LEN_D, phase, 1,i)) -static float poly_fir_coefs_d[POLY_FIR_LEN_D * PHASES_D * 2]; - -static float poly_fir1_d(float const * input, uint32_t frac) -{ - int i = 0, phase = (int)(frac >> (32 - PHASE_BITS_D)); - float sum = 0, x = (float)(frac << PHASE_BITS_D) * (float)(1 / MULT32); - _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - assert(i == POLY_FIR_LEN_D); - return (float)sum; -} -#undef a -#undef b -#define a (coef(poly_fir_coefs_u, 1, POLY_FIR_LEN_U, phase, 0,i)) -#define b (coef(poly_fir_coefs_u, 1, POLY_FIR_LEN_U, phase, 1,i)) -static float poly_fir_coefs_u[POLY_FIR_LEN_U * PHASES_U * 2]; - -static float poly_fir1_u(float const * input, uint32_t frac) -{ - int i = 0, phase = (int)(frac >> (32 - PHASE_BITS_U)); - float sum = 0, x = (float)(frac << PHASE_BITS_U) * (float)(1 / MULT32); - _ _ _ _ _ _ _ _ _ _ _ _ - assert(i == POLY_FIR_LEN_U); - return (float)sum; -} -#undef a -#undef b -#undef _ - -#define ADD_TO(x,y) x.all += y.all -#define SUBTRACT_FROM(x,y) x.all -= y.all -#define FRAC(x) x.part.frac -#define INT(x) x.part.integer - -typedef struct { - union { - int64_t all; -#if HAVE_BIGENDIAN - struct {int32_t integer; uint32_t frac;} part; -#else - struct {uint32_t frac; int32_t integer;} part; -#endif - } at, step, step_step; - float const * input; - int len, stage_num; - bool is_d; /* true: downsampling at x2 rate; false: upsampling at 1x rate. */ - double step_mult; -} stream_t; - -static int poly_fir_d(stream_t * s, float * output, int olen) -{ - int i; - float const * input = s->input - POLY_FIR_LEN_D / 2 + 1; - for (i = 0; i < olen && INT(s->at) < s->len; ++i) { - output[i] = poly_fir1_d(input + INT(s->at), FRAC(s->at)); - ADD_TO(s->at, s->step); - if (!(INT(s->at) < s->len)) { - SUBTRACT_FROM(s->at, s->step); - break; - } - output[++i] = poly_fir1_d(input + INT(s->at), FRAC(s->at)); - ADD_TO(s->at, s->step); - ADD_TO(s->step, s->step_step); - } - return i; -} - -static int poly_fir_fade_d( - stream_t * s, float const * vol, int step, float * output, int olen) -{ - int i; - float const * input = s->input - POLY_FIR_LEN_D / 2 + 1; - for (i = 0; i < olen && INT(s->at) < s->len; ++i, vol += step) { - output[i] += *vol * poly_fir1_d(input + INT(s->at), FRAC(s->at)); - ADD_TO(s->at, s->step); - if (!(INT(s->at) < s->len)) { - SUBTRACT_FROM(s->at, s->step); - break; - } - output[++i] += *(vol += step) * poly_fir1_d(input + INT(s->at),FRAC(s->at)); - ADD_TO(s->at, s->step); - ADD_TO(s->step, s->step_step); - } - return i; -} - -static int poly_fir_u(stream_t * s, float * output, int olen) -{ - int i; - float const * input = s->input - POLY_FIR_LEN_U / 2 + 1; - for (i = 0; i < olen && INT(s->at) < s->len; ++i) { - output[i] = poly_fir1_u(input + INT(s->at), FRAC(s->at)); - ADD_TO(s->at, s->step); - ADD_TO(s->step, s->step_step); - } - return i; -} - -static int poly_fir_fade_u( - stream_t * s, float const * vol, int step, float * output, int olen) -{ - int i; - float const * input = s->input - POLY_FIR_LEN_U / 2 + 1; - for (i = 0; i < olen && INT(s->at) < s->len; i += 2, vol += step) { - output[i] += *vol * poly_fir1_u(input + INT(s->at), FRAC(s->at)); - ADD_TO(s->at, s->step); - ADD_TO(s->step, s->step_step); - } - return i; -} - -#define shiftr(x,by) ((by) < 0? (x) << (-(by)) : (x) >> (by)) -#define shiftl(x,by) shiftr(x,-(by)) -#define stage_occupancy(s) (fifo_occupancy(&(s)->fifo) - 4*HALF_FIR_LEN_2) -#define stage_read_p(s) ((float *)fifo_read_ptr(&(s)->fifo) + 2*HALF_FIR_LEN_2) -#define stage_preload(s) memset(fifo_reserve(&(s)->fifo, (s)->preload), \ - 0, sizeof(float) * (size_t)(s)->preload); - -typedef struct { - fifo_t fifo; - double step_mult; - int is_fast, x_fade_len, preload; -} stage_t; - -typedef struct { - int num_stages0, num_stages, flushing; - int fade_len, slew_len, xfade, stage_inc, switch_stage_num; - double new_io_ratio, default_io_ratio; - stage_t * stages; - fifo_t output_fifo; - half_iir_t halfer; - stream_t current, fadeout; /* Current/fade-in, fadeout streams. */ -} rate_t; - -static float fade_coefs[(2 << FADE_LEN_BITS) + 1]; - -static void vr_init(rate_t * p, double default_io_ratio, int num_stages, double mult) -{ - int i; - assert(num_stages >= 0); - memset(p, 0, sizeof(*p)); - - p->num_stages0 = num_stages; - p->num_stages = num_stages = max(num_stages, 1); - p->stages = (stage_t *)calloc((unsigned)num_stages + 1, sizeof(*p->stages)) + 1; - for (i = -1; i < p->num_stages; ++i) { - stage_t * s = &p->stages[i]; - fifo_create(&s->fifo, sizeof(float)); - s->step_mult = 2 * MULT32 / shiftl(2, i); - s->preload = i < 0? 0 : i == 0? 2 * HALF_FIR_LEN_2 : 3 * HALF_FIR_LEN_2 / 2; - stage_preload(s); - s->is_fast = true; - lsx_debug("%-3i preload=%i", i, s->preload); - } - fifo_create(&p->output_fifo, sizeof(float)); - p->default_io_ratio = default_io_ratio; - if (fade_coefs[0]==0) { - for (i = 0; i < iAL(fade_coefs); ++i) - fade_coefs[i] = (float)(.5 * (1 + cos(M_PI * i / (AL(fade_coefs) - 1)))); - prepare_coefs(poly_fir_coefs_u, POLY_FIR_LEN_U, PHASES0_U, PHASES_U, coefs0_u, mult); - prepare_coefs(poly_fir_coefs_d, POLY_FIR_LEN_D, PHASES0_D, PHASES_D, coefs0_d, mult *.5); - } - assert(fade_coefs[0]); -} - -static void enter_new_stage(rate_t * p, int occupancy0) -{ - p->current.len = shiftr(occupancy0, p->current.stage_num); - p->current.input = stage_read_p(&p->stages[p->current.stage_num]); - - p->current.step_mult = p->stages[p->current.stage_num].step_mult; - p->current.is_d = p->current.stage_num >= 0; - if (p->current.is_d) - p->current.step_mult *= .5; -} - -static void set_step(stream_t * p, double io_ratio) -{ - p->step.all = (int64_t)(io_ratio * p->step_mult + .5); -} - -static bool set_step_step(stream_t * p, double io_ratio, int slew_len) -{ - int64_t dif; - int difi; - stream_t tmp = *p; - set_step(&tmp, io_ratio); - dif = tmp.step.all - p->step.all; - dif = dif < 0? dif - (slew_len >> 1) : dif + (slew_len >> 1); - difi = (int)dif; /* Try to avoid int64_t div. */ - p->step_step.all = difi == dif? difi / slew_len : dif / slew_len; - return p->step_step.all != 0; -} - -static void vr_set_io_ratio(rate_t * p, double io_ratio, size_t slew_len) -{ - assert(io_ratio > 0); - if (slew_len) { - if (!set_step_step(&p->current, io_ratio, p->slew_len = (int)slew_len)) - p->slew_len = 0, p->new_io_ratio = 0, p->fadeout.step_step.all = 0; - else { - p->new_io_ratio = io_ratio; - if (p->fade_len) - set_step_step(&p->fadeout, io_ratio, p->slew_len); - } - } - else { - if (p->default_io_ratio!=0) { /* Then this is the first call to this fn. */ - int octave = (int)floor(log(io_ratio) / M_LN2); - p->current.stage_num = octave < 0? -1 : min(octave, p->num_stages0-1); - enter_new_stage(p, 0); - } - else if (p->fade_len) - set_step(&p->fadeout, io_ratio); - set_step(&p->current, io_ratio); - if (p->default_io_ratio!=0) FRAC(p->current.at) = FRAC(p->current.step) >> 1; - p->default_io_ratio = 0; - } -} - -static bool do_input_stage(rate_t * p, int stage_num, int sign, int min_stage_num) -{ - int i = 0; - float * dest; - stage_t * s = &p->stages[stage_num]; - stage_t * s1 = &p->stages[stage_num - sign]; - float const * src = (float *)fifo_read_ptr(&s1->fifo) + HALF_FIR_LEN_2; - int len = shiftr(fifo_occupancy(&s1->fifo) - HALF_FIR_LEN_2 * 2, sign); - int already_done = fifo_occupancy(&s->fifo) - s->preload; - if ((len -= already_done) <= 0) - return false; - src += shiftl(already_done, sign); - - dest = fifo_reserve(&s->fifo, len); - if (stage_num < 0) for (; i < len; ++src) - dest[i++] = double_fir0(src), dest[i++] = double_fir1(src); - else { - bool should_be_fast = p->stage_inc; - if (!s->x_fade_len && stage_num == p->switch_stage_num) { - p->switch_stage_num = 0; - if (s->is_fast != should_be_fast) { - s->x_fade_len = 1 << FADE_LEN_BITS, s->is_fast = should_be_fast, ++p->xfade; - lsx_debug("xfade level %i, inc?=%i", stage_num, p->stage_inc); - } - } - if (s->x_fade_len) { - float const * vol1 = fade_coefs + (s->x_fade_len << 1); - float const * vol2 = fade_coefs + (((1 << FADE_LEN_BITS) - s->x_fade_len) << 1); - int n = min(len, s->x_fade_len); - /*lsx_debug("xfade level %i, inc?=%i len=%i n=%i", stage_num, p->stage_inc, s->x_fade_len, n);*/ - if (should_be_fast) - for (; i < n; vol2 += 2, vol1 -= 2, src += 2) - dest[i++] = *vol1 * fast_half_fir(src) + *vol2 * half_fir(src); - else for (; i < n; vol2 += 2, vol1 -= 2, src += 2) - dest[i++] = *vol2 * fast_half_fir(src) + *vol1 * half_fir(src); - s->x_fade_len -= n; - p->xfade -= !s->x_fade_len; - } - if (stage_num < min_stage_num) - for (; i < len; dest[i++] = fast_half_fir(src), src += 2); - else for (; i < len; dest[i++] = half_fir(src), src += 2); - } - if (p->flushing > 0) - stage_preload(s); - return true; -} - -static int vr_process(rate_t * p, int olen0) -{ - assert(p->num_stages > 0); - if (p->default_io_ratio!=0) - vr_set_io_ratio(p, p->default_io_ratio, 0); - { - float * output = fifo_reserve(&p->output_fifo, olen0); - int j, odone0 = 0, min_stage_num = p->current.stage_num; - int occupancy0, max_stage_num = min_stage_num; - if (p->fade_len) { - min_stage_num = min(min_stage_num, p->fadeout.stage_num); - max_stage_num = max(max_stage_num, p->fadeout.stage_num); - } - - for (j = min(min_stage_num, 0); j <= max_stage_num; ++j) - if (j && !do_input_stage(p, j, j < 0? -1 : 1, min_stage_num)) - break; - if (p->flushing > 0) - p->flushing = -1; - - occupancy0 = shiftl(max(0,stage_occupancy(&p->stages[max_stage_num])), max_stage_num); - p->current.len = shiftr(occupancy0, p->current.stage_num); - p->current.input = stage_read_p(&p->stages[p->current.stage_num]); - if (p->fade_len) { - p->fadeout.len = shiftr(occupancy0, p->fadeout.stage_num); - p->fadeout.input = stage_read_p(&p->stages[p->fadeout.stage_num]); - } - - while (odone0 < olen0) { - int odone, odone2, olen = olen0 - odone0, stage_dif = 0, shift; - float buf[64 << 1]; - - olen = min(olen, (int)(AL(buf) >> 1)); - if (p->slew_len) - olen = min(olen, p->slew_len); - else if (p->new_io_ratio!=0) { - set_step(&p->current, p->new_io_ratio); - set_step(&p->fadeout, p->new_io_ratio); - p->fadeout.step_step.all = p->current.step_step.all = 0; - p->new_io_ratio = 0; - } - if (!p->flushing && !p->fade_len && !p->xfade) { - if (p->current.is_d) { - if (INT(p->current.step) && FRAC(p->current.step)) - stage_dif = 1, ++max_stage_num; - else if (!INT(p->current.step) && FRAC(p->current.step) < (1u << 31)) - stage_dif = -1, --min_stage_num; - } else if (INT(p->current.step) > 1 && FRAC(p->current.step)) - stage_dif = 1, ++max_stage_num; - } - if (stage_dif) { - int n = p->current.stage_num + stage_dif; - if (n >= p->num_stages) - --max_stage_num; - else { - p->stage_inc = stage_dif > 0; - p->fadeout = p->current; - p->current.stage_num += stage_dif; - if (!p->stage_inc) - p->switch_stage_num = p->current.stage_num; - if ((p->current.stage_num < 0 && stage_dif < 0) || - (p->current.stage_num > 0 && stage_dif > 0)) { - stage_t * s = &p->stages[p->current.stage_num]; - fifo_clear(&s->fifo); - stage_preload(s); - s->is_fast = false; - do_input_stage(p, p->current.stage_num, stage_dif, p->current.stage_num); - } - if (p->current.stage_num > 0 && stage_dif < 0) { - int idone = INT(p->current.at); - stage_t * s = &p->stages[p->current.stage_num]; - fifo_trim_to(&s->fifo, 2 * HALF_FIR_LEN_2 + idone + (POLY_FIR_LEN_D >> 1)); - do_input_stage(p, p->current.stage_num, 1, p->current.stage_num); - } - enter_new_stage(p, occupancy0); - shift = -stage_dif; -#define lshift(x,by) (x)=(by)>0?(x)<<(by):(x)>>-(by) - lshift(p->current.at.all, shift); - shift += p->fadeout.is_d - p->current.is_d; - lshift(p->current.step.all, shift); - lshift(p->current.step_step.all, shift); - p->fade_len = AL(fade_coefs) - 1; - lsx_debug("switch from stage %i to %i, x2 from %i to %i", p->fadeout.stage_num, p->current.stage_num, p->fadeout.is_d, p->current.is_d); - } - } - - if (p->fade_len) { - float const * vol1 = fade_coefs + p->fade_len; - float const * vol2 = fade_coefs + (iAL(fade_coefs) - 1 - p->fade_len); - int olen2 = (olen = min(olen, p->fade_len >> 1)) << 1; - - /* x2 is more fine-grained so may fail to produce a pair of samples - * where x1 would not (the x1 second sample is a zero so is always - * available). So do x2 first, then feed odone to the second one. */ - memset(buf, 0, sizeof(*buf) * (size_t)olen2); - if (p->current.is_d && p->fadeout.is_d) { - odone = poly_fir_fade_d(&p->current, vol1,-1, buf, olen2); - odone2 = poly_fir_fade_d(&p->fadeout, vol2, 1, buf, odone); - } else if (p->current.is_d) { - odone = poly_fir_fade_d(&p->current, vol1,-1, buf, olen2); - odone2 = poly_fir_fade_u(&p->fadeout, vol2, 2, buf, odone); - } else { - assert(p->fadeout.is_d); - odone = poly_fir_fade_d(&p->fadeout, vol2, 1, buf, olen2); - odone2 = poly_fir_fade_u(&p->current, vol1,-2, buf, odone); - } - assert(odone == odone2); - (void)odone2; - p->fade_len -= odone; - if (!p->fade_len) { - if (p->stage_inc) - p->switch_stage_num = min_stage_num++; - else - --max_stage_num; - } - half_iir(&p->halfer, &output[odone0], buf, odone >>= 1); - } - else if (p->current.is_d) { - odone = poly_fir_d(&p->current, buf, olen << 1) >> 1; - half_iir(&p->halfer, &output[odone0], buf, odone); - } - else { - odone = poly_fir_u(&p->current, &output[odone0], olen); - if (p->num_stages0) - half_phase(&p->halfer, &output[odone0], odone); - } - odone0 += odone; - if (p->slew_len) - p->slew_len -= odone; - if (odone != olen) - break; /* Need more input. */ - } { - int from = max(0, max_stage_num), to = min(0, min_stage_num); - int i, idone = shiftr(INT(p->current.at), from - p->current.stage_num); - INT(p->current.at) -= shiftl(idone, from - p->current.stage_num); - if (p->fade_len) - INT(p->fadeout.at) -= shiftl(idone, from - p->fadeout.stage_num); - for (i = from; i >= to; --i, idone <<= 1) - fifo_read(&p->stages[i].fifo, idone, NULL); - } - fifo_trim_by(&p->output_fifo, olen0 - odone0); - return odone0; - } -} - -static float * vr_input(rate_t * p, float const * input, size_t n) -{ - return fifo_write(&p->stages[0].fifo, (int)n, input); -} - -static float const * vr_output(rate_t * p, float * output, size_t * n) -{ - fifo_t * fifo = &p->output_fifo; - if (1 || !p->num_stages0) - return fifo_read(fifo, (int)(*n = min(*n, (size_t)fifo_occupancy(fifo))), output); - else { /* Ignore this complication for now. */ - int const IIR_DELAY = 2; - float * ptr = fifo_read_ptr(fifo); - int olen = min((int)*n, max(0, fifo_occupancy(fifo) - IIR_DELAY)); - *n = (size_t)olen; - if (output) - memcpy(output, ptr + IIR_DELAY, *n * sizeof(*output)); - fifo_read(fifo, olen, NULL); - return ptr + IIR_DELAY; - } -} - -static void vr_flush(rate_t * p) -{ - if (!p->flushing) { - stage_preload(&p->stages[0]); - ++p->flushing; - } -} - -static void vr_close(rate_t * p) -{ - int i; - - fifo_delete(&p->output_fifo); - for (i = -1; i < p->num_stages; ++i) { - stage_t * s = &p->stages[i]; - fifo_delete(&s->fifo); - } - free(p->stages - 1); -} - -static double vr_delay(rate_t * p) -{ - return 100; /* TODO */ - (void)p; -} - -static void vr_sizes(size_t * shared, size_t * channel) -{ - *shared = 0; - *channel = sizeof(rate_t); -} - -static char const * vr_create(void * channel, void * shared,double max_io_ratio, - void * q_spec, void * r_spec, double scale) -{ - double x = max_io_ratio; - int n; - for (n = 0; x > 1; x *= .5, ++n); - vr_init(channel, max_io_ratio, n, scale); - return 0; - (void)shared, (void)q_spec, (void)r_spec; -} - -static char const * vr_id(void) -{ - return "vr32"; -} - -typedef void (* fn_t)(void); -fn_t _soxr_vr32_cb[] = { - (fn_t)vr_input, - (fn_t)vr_process, - (fn_t)vr_output, - (fn_t)vr_flush, - (fn_t)vr_close, - (fn_t)vr_delay, - (fn_t)vr_sizes, - (fn_t)vr_create, - (fn_t)vr_set_io_ratio, - (fn_t)vr_id, -}; diff --git a/C/src/soxr-0.1.3/tests/1-delay-clear.c b/C/src/soxr-0.1.3/tests/1-delay-clear.c deleted file mode 100644 index ba4d47c0..00000000 --- a/C/src/soxr-0.1.3/tests/1-delay-clear.c +++ /dev/null @@ -1,64 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-15 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -/* Test 1: exercises soxr_delay and soxr_clear */ - -#ifdef NDEBUG /* N.B. assert used with active statements so enable always. */ -#undef NDEBUG /* Must undef above assert.h or other that might include it. */ -#endif - -#include -#include "../examples/examples-common.h" - -#define ranqd1(x) ((x) = 1664525 * (x) + 1013904223) /* int32_t x */ -#define franqd1(x) (float)(ranqd1(x) * (1. / (65536. * 32768.))) /* [-1,1) */ - -#define irate 9600 -#define orate 4410 - -int main(int argc, char const * arg[]) -{ - soxr_error_t error; - int32_t ran = 0; - int j; - - soxr_t soxr = soxr_create(irate, orate, 1, &error, NULL, NULL, NULL); - assert(!error); - - for (j=0; j<2; ++j) { - float ibuf[irate], out[orate+2], obuf[orate+2], * ibuf1 = ibuf; - size_t ilen = AL(ibuf)-1, olen = AL(obuf), i, odone = 0, odone0, odone1=0; - soxr_quality_spec_t q_spec = soxr_quality_spec(SOXR_HQ, 0); - - for (i=0; i= 0); - fprintf(stderr, "%5u %5u %5u\n", - (unsigned)ilen, max_out_samples, (unsigned)odone); - assert(max_out_samples+odone==odone0); - error = soxr_process(soxr, ibuf1, ilen, NULL, obuf+odone, olen, &odone1); - assert(!error); - odone += odone1; - ibuf1 = NULL, ilen = 0; - olen = min(100, AL(obuf)-odone); - } - assert(odone==odone0); - - for (i=0; i44k1 and that results are same for each: -ir=96000 -or=44100 -for i in 1 2; do - prev="" - sox -r $ir -n 0.f32 synth $len sin 0+`expr $ir / 2` - for f in `find . -type f -executable -name "[2-4]*"`; do - $vg $f $ir $or < 0.f32 > $f.f32 - test x$prev != x && cmp $f.f32 $prev - prev=$f.f32 - done - or=96000 - ir=44100 -done -rm *.f32 - - - -# Exercise VR making sure that varied internal stage reconfigurations occur: -variations=(slow-sweep fast-changing) -signals=(sine-wave saw-tooth-wave) -for n in 0 1 2 3; do - signal=${signals[`expr $n % 2 || true`]} - variation=${variations[`expr $n / 2 || true`]} - $vg ./5-variable-rate $n | sox -tf32 -r44100 -c1 - -n spectrogram -z130 -hw$w -o v$n-$w.png -X 50 -c "variation:$variation signal:$signal" - vg="" -done diff --git a/C/src/soxr-0.1.3/tests/io-test b/C/src/soxr-0.1.3/tests/io-test deleted file mode 100755 index 608bc9ab..00000000 --- a/C/src/soxr-0.1.3/tests/io-test +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env bash -set -e - -# SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net -# Licence for this file: LGPL v2.1 See LICENCE for details. - -# Tests IO - - - -ir=65537 -or=44100 -len=16 -f=1/32768 -g=32768:0 -tool=./3-options-input-fn -w=$(echo -e "`sox --ver |sed 's/.*SoX v//'` d\n14.4.1 k"|sort -Vr|head -1|sed 's/.* //') - -types=(f32 f64 s32 s16) - -zs=(180 180 180 180 180 120 120 120 120) - -do_one() { - it=${types[$1]}; ot=${types[`expr $2 % 4 || true`]} - $tool $ir $or $c $1 $2 $3 < $c.$it > a.$ot - sox -r $or -c $c a.$ot -n spectrogram -X50 -hw$w -z${zs[$n]} -o io$c$n-$w.png -c "io-test i:$it o:$ot ($2) q:$3" - ./4-split-channels $ir $or $c $1 $2 $3 < $c.$it > b.$ot - [ $2 != 3 ] && cmp a.$ot b.$ot || - test $(sox -mv-1 -r$or -c$c a.$ot -r$or -c$c b.$ot -n stats 2>&1 |grep Pk\ l|tr ' ' '\n'|grep '[0-9]'|uniq) = -84.29 - rm [ab].$ot - n=`expr $n + 1` -} - -test z$1 != z && j=$1 || j=1 - -for c in `seq 1 $j`; do - for n in `seq 0 3`; do - sox -R -r $ir -n $c.${types[$n]} synth $len sin $f gain -.1 - done - - n=0 - do_one 1 2 5 - do_one 2 0 5 - for m in `seq 0 3`; do do_one $m $m 5; done - do_one 3 2 3 - do_one 0 3 3 - do_one 0 11 3 - - f="$f sin $g" - g=0+32768 -done - -rm ?.[sf][0-9][0-9] - - - -# Check conversion between differing I/O types, but no rate-change: - -for i in 1 2 3; do - prev="" - sox -n -c $i 0.f32 synth $len gain -.1 - $tool 1 1 $i 0 2 < 0.f32 | $tool 1 1 $i 2 0 > 1.f32 - cmp [01].f32 -done -rm *.f32 diff --git a/C/src/soxr-0.1.3/tests/large-ratio-test b/C/src/soxr-0.1.3/tests/large-ratio-test deleted file mode 100755 index 540c5df3..00000000 --- a/C/src/soxr-0.1.3/tests/large-ratio-test +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env bash -set -e - -# SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net -# Licence for this file: LGPL v2.1 See LICENCE for details. - -# Tests interpolating then decimating by the same, large ratio. - -tool=../examples/3-options-input-fn -w=$(echo -e "`sox --ver |sed 's/.*SoX v//'` d\n14.4.1 k"|sort -Vr|head -1|sed 's/.* //') -q=4 -test x$1 = x && ratio=1e5 || ratio=$1 -test x$2 = x && rate=8000 || rate=$2 - -sox -r$rate -n 1.s32 synth 10 sin 0:`expr $rate / 2` vol .9375 -sync - -time { $tool 1 $ratio 1 2 1 $q a < 1.s32 | $tool $ratio 1 1 1 2 $q a > 2.s32;} - -sox -mv-1 -r$rate -c1 1.s32 -r$rate -c1 2.s32 -n spectrogram -hw$w -z150 -o lr-$w.png -c "large-ratio-test q:$q ratio:$ratio" - -rm [12].s32 diff --git a/C/src/soxr-0.1.3/tests/phase-test b/C/src/soxr-0.1.3/tests/phase-test deleted file mode 100755 index 3c342689..00000000 --- a/C/src/soxr-0.1.3/tests/phase-test +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env bash -set -e - -# SoX Resampler Library Copyright (c) 2007-15 robs@users.sourceforge.net -# Licence for this file: LGPL v2.1 See LICENCE for details. - -# Tests varying phase-response. - -tool=./3-options-input-fn -w=$(echo -e "`sox --ver |sed 's/.*SoX v//'` d\n14.4.1 k"|sort -Vr|head -1|sed 's/.* //') -spec="spectrogram -z160 -Z-20 -X 2000 -w$w -ho" -ext=f32; e=0 -rate1=48000 -rate2=44100 - -for n in 1 2; do - sox -r $rate1 -n 0.$ext synth 1s sq pad .03 .03 gain -1 - - # Test the following combinations: - names=(linear-phase intermediate-phase maximum-phase minimum-phase) - filters=(standard-filter steep-filter) - - for q in `seq 0 7`; do - f=ph-$rate2-q$q-$w - name=${names[`expr $q % 4 || true`]} - filter=${filters[`expr $q / 4 || true`]} - $tool $rate1 $rate2 1 $e $e $q'6' < 0.$ext | sox -c1 -r$rate2 -t $ext - -n $spec $f.png -c "ph-test $filter $name" - done - - # Test specific phase-response percentages: - for q in `seq 0 20 100`; do - f=ph-$rate2-p`printf %03u $q`-$w - $tool $rate1 $rate2 1 $e $e 46 0 0 0 $q < 0.$ext | sox -c1 -r$rate2 -t $ext - -n $spec $f.png -c "ph-test phase:${q}%" - done - - r=$rate1; rate1=$rate2; rate2=$r -done - -rm 0.$ext diff --git a/C/src/soxr-0.1.3/tests/q-test b/C/src/soxr-0.1.3/tests/q-test deleted file mode 100755 index f274cb59..00000000 --- a/C/src/soxr-0.1.3/tests/q-test +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/env bash -set -e - -# SoX Resampler Library Copyright (c) 2007-15 robs@users.sourceforge.net -# Licence for this file: LGPL v2.1 See LICENCE for details. - -# Tests conversion qualities 0..7 & variable-rate. - - - -tool=./3-options-input-fn -w=$(echo -e "`sox --ver |sed 's/.*SoX v//'` d\n14.4.1 k"|sort -Vr|head -1|sed 's/.* //') -ext=f64; e=1 -c=1 -q1=0; q2=7 -rates=48000 -zs=(50 87 87 87 111 135 159 180 95) - -zz() { - echo "spectrogram -z${zs[$1]} -Z-30 -w$w -ho" -} - -for rate0 in $rates; do - -rate1=$rate0 -rate2=44100 - -for n in 1 2; do - -rate1n=`expr $rate1 / 2` - - - -# Convert sweep, for spectrogram: - -sox -r $rate1 -n -c $c 0.$ext synth 8 sin 0:$rate1n gain -1 - -for q in `seq $q1 $q2`; do - f=qa-$rate1-$rate2-$q - $tool $rate1 $rate2 $c $e $e $q 0 < 0.$ext | sox -c$c -r$rate2 -t $ext - -n $(zz $q) $f-$w.png -c $f -done -q=8 -f=qa-$rate1-$rate2-v -$tool $rate1 $rate2 $c $e $e 4 20 < 0.$ext | sox -c$c -r$rate2 -t $ext - -n $(zz $q) $f-$w.png -c $f - - - -# Convert impulse, for spectrogram: - -#: << : -sox -r $rate1 -n 0.$ext synth 1s sq pad .03 .03 gain -1 - -for q in `seq $q1 $q2`; do - f=qb-$rate1-$rate2-$q - $tool $rate1 $rate2 1 $e $e $q 0 < 0.$ext | sox -c1 -r$rate2 -t $ext - $f.wav -done -q=8 -f=qb-$rate1-$rate2-v -$tool $rate1 $rate2 1 $e $e 4 20 < 0.$ext | sox -c1 -r$rate2 -t $ext - $f.wav - -# Combine impuse responses into multi-channel file (for inspection in Audacity): -sox -M qb-$rate1-$rate2-?.wav q$rate1-$rate2.wav - -rm qb-$rate1-$rate2-?.wav -: - -rate1=44100 -rate2=$rate0 - -done -done - -rm 0.$ext diff --git a/C/src/soxr-0.1.3/tests/scripts b/C/src/soxr-0.1.3/tests/scripts deleted file mode 100755 index 8b6023f1..00000000 --- a/C/src/soxr-0.1.3/tests/scripts +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env bash -set -e - -# SoX Resampler Library Copyright (c) 2007-15 robs@users.sourceforge.net -# Licence for this file: LGPL v2.1 See LICENCE for details. - -../../tests/bandwidth-test -../../tests/eg-test -../../tests/io-test 3 -../../tests/large-ratio-test -../../tests/phase-test -../../tests/q-test -../../tests/time-test 1 -../../tests/time-test 2 diff --git a/C/src/soxr-0.1.3/tests/throughput-test b/C/src/soxr-0.1.3/tests/throughput-test deleted file mode 100755 index aef36f6c..00000000 --- a/C/src/soxr-0.1.3/tests/throughput-test +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh -set -e - -# SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net -# Licence for this file: LGPL v2.1 See LICENCE for details. - -test -r throughput.exe && wine=wine - -test /$1 = / && list="`seq 0 3`" || list="$*" - -for n in $list; do $wine ./throughput 44.1 48 1 0 $n 4; done diff --git a/C/src/soxr-0.1.3/tests/throughput-test.bat b/C/src/soxr-0.1.3/tests/throughput-test.bat deleted file mode 100644 index 46b8f7d1..00000000 --- a/C/src/soxr-0.1.3/tests/throughput-test.bat +++ /dev/null @@ -1,5 +0,0 @@ -@echo off -rem SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net -rem Licence for this file: LGPL v2.1 See LICENCE for details. - -for /L %%i in (0,1,3) DO throughput 44.1 48 1 0 %%i diff --git a/C/src/soxr-0.1.3/tests/throughput.c b/C/src/soxr-0.1.3/tests/throughput.c deleted file mode 100644 index c52b885d..00000000 --- a/C/src/soxr-0.1.3/tests/throughput.c +++ /dev/null @@ -1,141 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -#include -#include "rint.h" -#include "../examples/examples-common.h" - -#define k 1000 - -#if defined _WIN32 - #define WIN32_LEAN_AND_MEAN - #include - #define timerStart(msecs) LARGE_INTEGER start, stop, tmp; \ - QueryPerformanceCounter(&start), QueryPerformanceFrequency(&tmp), \ - stop.QuadPart = (msecs * tmp.QuadPart + k/2) / k - #define timerRunning() (QueryPerformanceCounter(&tmp), \ - (tmp.QuadPart-start.QuadPart < stop.QuadPart)) -#else - #include - #if defined timeradd - #define K k - #define tv_frac tv_usec - #define timespec timeval - #define get_time(x) gettimeofday(x, NULL) - #else - #include - #include - #if defined _POSIX_TIMERS && _POSIX_TIMERS > 0 - #define K (k*k) - #define tv_frac tv_nsec - #if defined _POSIX_MONOTONIC_CLOCK - #define get_time(x) clock_gettime(CLOCK_MONOTONIC, x) - #else - #define get_time(x) clock_gettime(CLOCK_REALTIME, x) - #endif - #else - #include - #define K 1 - #define tv_frac millitm - #define tv_sec time - #define timespec timeb - #define get_time(x) ftime(x) - #endif - #endif - - #define timerStart(msecs) struct timespec stop, tmp; get_time(&stop), \ - stop.tv_frac += (msecs%k)*K, \ - stop.tv_sec += msecs/k + stop.tv_frac/(K*k), \ - stop.tv_frac %= K*k - #define timerRunning() (get_time(&tmp), \ - (tmp.tv_sec < stop.tv_sec || tmp.tv_frac < stop.tv_frac)) -#endif - -int main(int n, char const * arg[]) -{ - char const * const arg0 = n? --n, *arg++ : "", * engine = ""; - double const irate = n? --n, atof(*arg++) : 96000.; - double const orate = n? --n, atof(*arg++) : 44100.; - unsigned const chans = n? --n, (unsigned)atoi(*arg++) : 1; - soxr_datatype_t const itype = n? --n, (soxr_datatype_t)atoi(*arg++) : 0; - unsigned const ospec = n? --n, (soxr_datatype_t)atoi(*arg++) : 0; - unsigned long const q_recipe= n? --n, strtoul(*arg++, 0, 16) : SOXR_HQ; - unsigned long const q_flags = n? --n, strtoul(*arg++, 0, 16) : 0; - double const passband_end = n? --n, atof(*arg++) : 0; - double const stopband_begin = n? --n, atof(*arg++) : 0; - double const phase_response = n? --n, atof(*arg++) : -1; - int const use_threads = n? --n, atoi(*arg++) : 1; - soxr_datatype_t const otype = ospec & 3; - - soxr_quality_spec_t q_spec = soxr_quality_spec(q_recipe, q_flags); - soxr_io_spec_t io_spec = soxr_io_spec(itype, otype); - soxr_runtime_spec_t const runtime_spec = soxr_runtime_spec(!use_threads); - - /* Allocate resampling input and output buffers in proportion to the input - * and output rates: */ - #define buf_total_len 15000 /* In samples per channel. */ - size_t const osize = soxr_datatype_size(otype) * chans; - size_t const isize = soxr_datatype_size(itype) * chans; - size_t const olen0= (size_t)(orate * buf_total_len / (irate + orate) + .5); - size_t const olen = min(max(olen0, 1), buf_total_len - 1); - size_t const ilen = buf_total_len - olen; - void * const obuf = malloc(osize * olen); - void * const ibuf = malloc(isize * ilen); - - size_t odone = 0, clips = 0, omax = 0, i; - soxr_error_t error; - soxr_t soxr; - int32_t seed = 0; - char const * e = getenv("SOXR_THROUGHPUT_GAIN"); - double gain = e? atof(e) : .5; - - /* Overrides (if given): */ - if (passband_end > 0) q_spec.passband_end = passband_end / 100; - if (stopband_begin > 0) q_spec.stopband_begin = stopband_begin / 100; - if (phase_response >=0) q_spec.phase_response = phase_response; - io_spec.flags = ospec & ~7u; - - /* Create a stream resampler: */ - soxr = soxr_create( - irate, orate, chans, /* Input rate, output rate, # of channels. */ - &error, /* To report any error during creation. */ - &io_spec, &q_spec, &runtime_spec); - -#define ranqd1(x) ((x) = 1664525 * (x) + 1013904223) /* int32_t x */ -#define dranqd1(x) (ranqd1(x) * (1. / (65536. * 32768.))) /* [-1,1) */ -#define RAND (dranqd1(seed) * gain) -#define DURATION_MSECS 125 -#define NUM_ATTEMPTS 8 - - if (!error) { /* If all is well, run the resampler: */ - engine = soxr_engine(soxr); - switch (itype & 3) { - case 0: for (i=0;i /dev/null 2> $ERR - echo $rate1 '-->' $rate2 c=$c q=$q t=`cat $TIME` `cat $ERR | sed 's/.*(/(/'` - done - rate1=$rate0 - rate2=44100 - done -done - -rm 0.$ext diff --git a/C/src/soxr-0.1.3/tests/vector-cmp.c b/C/src/soxr-0.1.3/tests/vector-cmp.c deleted file mode 100644 index f90cc7fa..00000000 --- a/C/src/soxr-0.1.3/tests/vector-cmp.c +++ /dev/null @@ -1,56 +0,0 @@ -/* SoX Resampler Library Copyright (c) 2007-16 robs@users.sourceforge.net - * Licence for this file: LGPL v2.1 See LICENCE for details. */ - -/* Utility used to help test the library; not for general consumption. - * - * Measure the peak bit difference between two files. */ - -#include -#include -#include "../src/rint.h" -#include "../examples/examples-common.h" - -#define TYPE 0 /* As vector-gen */ - -#if TYPE - #define sample_t double - #define N 50 - #define DIFF(s1,s2) abs(rint32((s1-s2)*ldexp(1,N-1))) -#else - #define sample_t int32_t - #define N 32 - #define DIFF(s1,s2) abs((int)(s1-s2)) -#endif - -int main(int argc, char const * arg[]) -{ - int two = !!arg[2][0]; - FILE * f1 = fopen(arg[1], "rb"), * f2 = two? fopen(arg[2], "rb") : 0; - double rate = atof (arg[3]), /* Sample-rate */ - skip_len = atof (arg[4]), /* Skip length in seconds */ - len = atof (arg[5]), /* Compare length in seconds */ r; - int i = 0, count = rint32(rate * len), max = 0, diff; - sample_t s1, s2; - - fseek(f1, rint32(rate * skip_len) * (int)sizeof(s1), SEEK_CUR); - if (two) { - fseek(f2, rint32(rate * skip_len) * (int)sizeof(s2), SEEK_CUR); - for (; i < count && - fread(&s1, sizeof(s1), 1, f1) && - fread(&s2, sizeof(s2), 1, f2); ++i) { - diff = DIFF(s1, s2); - max = max(max, diff); - } - } - else for (; i < count && fread(&s1, sizeof(s1), 1, f1); ++i) { - diff = DIFF(s1, 0); - max = max(max, diff); - } - - if (i != count) { - fprintf(stderr, "incorrect file length\n"); - return 1; - } - printf("%f\n", r = N-log(max)/log(2)); - return argc>6? r 1 - #include -#endif - -#include "math-wrap.h" -#include -#include - -#if TYPE - #if TYPE > 1 - #define modf modfq - #define cos cosq - #define sin sinq - #define PI M_PIq - #define real __float128 - #define atof(x) strtoflt128(x, 0) - #else - #define modf modfl - #define cos cosl - #define sin sinl - #define PI M_PIl - #define real long double - #endif - #define MULT 1 - #define OUT(d) double output = d -#else - #define PI M_PI - #define real double - #include "rint.h" - #define MULT (32768. * 65536 - 1/scale) - #define OUT(d) int32_t output = rint32(d) -#endif - -int main(int argc, char const * argv[]) -{ - real rate = atof(argv[1]), /* Rate for this vector */ - lead_in_len = atof(argv[2]), /* Lead-in length in seconds */ - len = atof(argv[3]), /* Sweep length (excl. lead_in_len) */ - f1 = atof(argv[4]), - f2 = atof(argv[5]), - scale = atof(argv[6]), /* For headroom */ - n1 = rate * -lead_in_len, - m = (f2 - f1) / (rate * len * 2), dummy; - FILE * file = fopen(argv[7], "wb"); - int i = (int)n1, err = !file || i != n1; - for (; !err && i < (int)(rate*(len+lead_in_len)+.5); ++i) { - real d = sin(2 * PI * modf((f1 + i * m) * i / rate, &dummy)); - OUT((double)(scale * MULT * d)); - err = fwrite(&output, sizeof(output), 1, file) != 1; - } - return err |!argc; -} diff --git a/Makefile b/Makefile deleted file mode 100644 index cde29237..00000000 --- a/Makefile +++ /dev/null @@ -1,51 +0,0 @@ -APP_NAME=pmomusic - -PREFIX := $(CURDIR)/C -SRC_DIR := $(PREFIX)/src/soxr-0.1.3 -INCLUDE_DIR := $(PREFIX)/include -LIB_DIR := $(PREFIX)/lib -BIN_DIR := $(PREFIX)/bin -CFLAGS = -O2 -fPIC -LDFLAGS := -LIBSOXR := $(LIB_DIR)/libsoxr.a - -.PHONY: all clean build web run test - -# Build Go app -build: web $(LIBSOXR) - go build -o bin/$(APP_NAME) ./cmd/$(APP_NAME) - -# Build web frontend -web: - @ echo Building the Web app - @ cd pmoapp/web && npm install && npm run build - @ echo Web app built - -# Run Go app -run: - go run ./cmd/$(APP_NAME) - -# Clean Go binary, web build, libsoxr build -clean: - rm -rf bin/$(APP_NAME) - rm -rf web/dist - @echo "==> Cleaning libsoxr build..." - # supprime les fichiers compilés libsoxr - rm -rf $(INCLUDE_DIR)/* $(LIB_DIR)/* - @echo "==> Clean done" - -# Compilation statique de libsoxr -$(LIBSOXR): - @echo "==> Building libsoxr statically..." - mkdir -p $(INCLUDE_DIR) $(LIB_DIR) $(BIN_DIR) - cd $(SRC_DIR) && ./go - # Installer dans PREFIX (headers et lib) - cd $(SRC_DIR)/Release && make install PREFIX=$(PREFIX) - @echo "==> libsoxr built: $(LIBSOXR)" - -# Build everything -all: build - -# Run Go tests (requires libsoxr built) -test: $(LIBSOXR) - CGO_ENABLED=1 go test ./... diff --git a/all.txt b/all.txt deleted file mode 100644 index 3b232c40..00000000 --- a/all.txt +++ /dev/null @@ -1,1327 +0,0 @@ -Et bien maintenant sans modifier aucune ligne du code que je te fournis ci dessous, développe la collection la plus complète possible de tests unitaire pour ces deux packages -IGNORE TOUTES LES INFÉRENCES. NE TRAVAILLE QUE SUR LE CODE FOURNI. L’OBJECTIF EST QUE LES TEST COMPILENT ET PASSENT. - -============== Debut des sources des packages =============== -------- pmosoxr/concurency_test.go ------ -//go:build cgo -// +build cgo - -package pmosoxr - -import ( - "math" - "sync" - "testing" - "time" -) - -// genStereoSine génère nFrames frames interlacées float32 (L,R identiques) à amplitude 0.2. -func genStereoSine(nFrames int, freq float64, sr float64) []float32 { - out := make([]float32, nFrames*2) - for i := 0; i < nFrames; i++ { - v := float32(0.2 * math.Sin(2*math.Pi*freq*float64(i)/sr)) - out[2*i] = v - out[2*i+1] = v - } - return out -} - -func TestResamplerConcurrentProcess(t *testing.T) { - inRate := 44100.0 - outRate := 48000.0 - channels := 2 - quality := MQ - - r, err := New(inRate, outRate, channels, quality) - if err != nil { - t.Fatalf("failed to create resampler: %v", err) - } - defer r.Delete() - - workers := 8 - iterations := 200 - framesPerIter := 256 - var wg sync.WaitGroup - errCh := make(chan error, workers) - totalProduced := int64(0) - var prodMu sync.Mutex - - for w := 0; w < workers; w++ { - wg.Add(1) - go func(id int) { - defer wg.Done() - for i := 0; i < iterations; i++ { - in := genStereoSine(framesPerIter, 440.0+float64(id), inRate) - ratio := outRate / inRate - outFrames := int(float64(framesPerIter)*ratio) + 64 - out := make([]float32, outFrames*2) - consumed, produced, perr := r.Process(in, out) - if perr != nil { - errCh <- perr - return - } - if consumed < 0 || produced < 0 { - errCh <- &testError{"negative sample count"} - return - } - if produced > len(out) { - errCh <- &testError{"produced > out buffer"} - return - } - prodMu.Lock() - totalProduced += int64(produced) - prodMu.Unlock() - time.Sleep(1 * time.Millisecond) - } - }(w) - } - - wg.Wait() - close(errCh) - - for e := range errCh { - t.Fatalf("resampler error: %v", e) - } - - if totalProduced == 0 { - t.Fatal("no samples produced") - } -} - -type testError struct { - s string -} - -func (e *testError) Error() string { return e.s } ------------------ -------- pmosoxr/quality.go ------ -package pmosoxr - -/* -#cgo CFLAGS: -I${SRCDIR}/../C/include - -#include -#include - -static soxr_quality_spec_t q_spec(int q) { - switch(q) { - case 0: return soxr_quality_spec(SOXR_QQ, 0); - case 1: return soxr_quality_spec(SOXR_LQ, 0); - case 2: return soxr_quality_spec(SOXR_MQ, 0); - case 3: return soxr_quality_spec(SOXR_HQ, 0); - case 4: return soxr_quality_spec(SOXR_VHQ, 0); - default: return soxr_quality_spec(SOXR_MQ, 0); - } -} -*/ -import "C" - -type Quality int - -const ( - QQ Quality = iota - LQ - MQ - HQ - VHQ -) - -func (q Quality) toC() C.soxr_quality_spec_t { - return C.q_spec(C.int(q)) -} ------------------ -------- pmosoxr/soxr.go ------ -//go:build cgo -// +build cgo - -package pmosoxr - -/* -#cgo CFLAGS: -I${SRCDIR}/../C/include -#cgo LDFLAGS: ${SRCDIR}/../C/lib/libsoxr.a -lomp - -#include -#include -*/ -import "C" - -import ( - "errors" - "sync" - "unsafe" -) - -type Resampler struct { - handle C.soxr_t - channels int - mu sync.Mutex - deleted bool -} - -func New(inRate, outRate float64, channels int, q Quality) (*Resampler, error) { - if channels != 2 { - return nil, errors.New("only stereo supported") - } - - var err C.soxr_error_t - qspec := q.toC() - - handle := C.soxr_create( - C.double(inRate), - C.double(outRate), - C.uint(channels), - &err, - nil, - &qspec, - nil, - ) - if handle == nil { - if err != nil { - return nil, errors.New(C.GoString(err)) - } - return nil, errors.New("soxr_create failed without error message") - } - return &Resampler{handle: handle, channels: channels}, nil -} - -func (r *Resampler) Process(in []float32, out []float32) (consumedSamples int, producedSamples int, err error) { - r.mu.Lock() - defer r.mu.Unlock() - - if r.deleted { - return 0, 0, errors.New("resampler deleted") - } - if r.handle == nil { - return 0, 0, errors.New("resampler not initialized") - } - if len(in)%r.channels != 0 || len(out)%r.channels != 0 { - return 0, 0, errors.New("buffer size not divisible by channel count") - } - - var idone, odone C.size_t - var inPtr C.soxr_in_t - var outPtr C.soxr_out_t - - if len(in) > 0 { - inPtr = C.soxr_in_t(unsafe.Pointer(&in[0])) - } - if len(out) > 0 { - outPtr = C.soxr_out_t(unsafe.Pointer(&out[0])) - } - - st := C.soxr_process( - r.handle, - inPtr, C.size_t(len(in)/r.channels), - &idone, - outPtr, C.size_t(len(out)/r.channels), - &odone, - ) - if st != nil { - return 0, 0, errors.New(C.GoString(st)) - } - return int(idone) * r.channels, int(odone) * r.channels, nil -} - -func (r *Resampler) Flush(out []float32) (int, error) { - r.mu.Lock() - defer r.mu.Unlock() - - if r.deleted { - return 0, errors.New("resampler deleted") - } - if r.handle == nil { - return 0, errors.New("resampler not initialized") - } - - var odone C.size_t - if len(out) == 0 { - return 0, nil - } - st := C.soxr_process(r.handle, nil, 0, nil, - C.soxr_out_t(unsafe.Pointer(&out[0])), C.size_t(len(out)/r.channels), &odone) - if st != nil { - return 0, errors.New(C.GoString(st)) - } - return int(odone) * r.channels, nil -} - -func (r *Resampler) Delete() { - r.mu.Lock() - defer r.mu.Unlock() - - if !r.deleted && r.handle != nil { - C.soxr_delete(r.handle) - r.handle = nil - r.deleted = true - } -} ------------------ -------- pmostream/audio.go ------ -package pmostream - -import ( - "fmt" - "os" - "strings" - - "github.com/gopxl/beep" - "github.com/gopxl/beep/flac" - "github.com/gopxl/beep/mp3" - "github.com/gopxl/beep/vorbis" - "github.com/gopxl/beep/wav" -) - -type streamerWithCloser struct { - beep.Streamer - closer func() error -} - -func (s *streamerWithCloser) Close() error { - if s.closer != nil { - return s.closer() - } - return nil -} - -func LoadAudio(uri string) (beep.Streamer, beep.Format, error) { - f, err := os.Open(uri) - if err != nil { - return nil, beep.Format{}, err - } - - var streamer beep.Streamer - var format beep.Format - - lowerURI := strings.ToLower(uri) - switch { - case strings.HasSuffix(lowerURI, ".flac"): - streamer, format, err = flac.Decode(f) - case strings.HasSuffix(lowerURI, ".wav"): - streamer, format, err = wav.Decode(f) - case strings.HasSuffix(lowerURI, ".mp3"): - streamer, format, err = mp3.Decode(f) - case strings.HasSuffix(lowerURI, ".ogg"): - streamer, format, err = vorbis.Decode(f) - default: - f.Close() - return nil, beep.Format{}, fmt.Errorf("unsupported format: %s", uri) - } - - if err != nil { - f.Close() - return nil, beep.Format{}, err - } - - return &streamerWithCloser{ - Streamer: streamer, - closer: f.Close, - }, format, nil -} ------------------ -------- pmostream/buffer.go ------ -package pmostream - -import ( - "sync" - "time" -) - -// AudioBuffer est un buffer circulaire thread-safe pour l'audio -type AudioBuffer struct { - mu sync.Mutex - cond *sync.Cond - chunks [][]byte - size int - format SampleFormat - readPos int - writePos int - closed bool -} - -// NewAudioBuffer crée un nouveau buffer circulaire -func NewAudioBuffer(size int, format SampleFormat) *AudioBuffer { - ab := &AudioBuffer{ - chunks: make([][]byte, size), - size: size, - format: format, - } - ab.cond = sync.NewCond(&ab.mu) - return ab -} - -// Available retourne le nombre de chunks disponibles pour lecture -func (ab *AudioBuffer) Available() int { - ab.mu.Lock() - defer ab.mu.Unlock() - return ab.availableLocked() -} - -// Write ajoute un chunk dans le buffer (écrase le plus ancien si plein) -func (ab *AudioBuffer) Write(chunk []byte) { - ab.mu.Lock() - defer ab.mu.Unlock() - if ab.closed { - return - } - - ab.chunks[ab.writePos] = chunk - ab.writePos = (ab.writePos + 1) % ab.size - if ab.writePos == ab.readPos { - // Écrase le plus ancien - ab.readPos = (ab.readPos + 1) % ab.size - } - - ab.cond.Broadcast() -} - -// Read lit un chunk du buffer, ou nil si vide ou fermé -func (ab *AudioBuffer) Read() []byte { - ab.mu.Lock() - defer ab.mu.Unlock() - - if ab.availableLocked() == 0 { - return nil - } - - chunk := ab.chunks[ab.readPos] - ab.chunks[ab.readPos] = nil - ab.readPos = (ab.readPos + 1) % ab.size - return chunk -} - -// WaitForData attend qu'au moins n chunks soient disponibles ou timeout/closed -func (ab *AudioBuffer) WaitForData(n int, timeout time.Duration) bool { - ab.mu.Lock() - defer ab.mu.Unlock() - - if n <= 0 { - n = 1 - } - - deadline := time.Now().Add(timeout) - - for ab.availableLocked() < n && !ab.closed { - if timeout <= 0 { - ab.cond.Wait() - } else { - remaining := time.Until(deadline) - if remaining <= 0 { - return false - } - - // Wait avec timeout en utilisant Wait + Broadcast classique - timer := time.NewTimer(remaining) - done := make(chan struct{}) - - go func() { - ab.cond.Wait() - close(done) - }() - - ab.mu.Unlock() - select { - case <-done: - // réveillé par Broadcast - if !timer.Stop() { - <-timer.C - } - case <-timer.C: - ab.mu.Lock() - return false - } - ab.mu.Lock() - } - } - - return ab.availableLocked() >= n && !ab.closed -} - -// Close ferme le buffer et réveille tous les Waiters -func (ab *AudioBuffer) Close() { - ab.mu.Lock() - defer ab.mu.Unlock() - if !ab.closed { - ab.closed = true - ab.cond.Broadcast() - } -} - -// availableLocked retourne le nombre de chunks disponibles, doit être appelé avec ab.mu locké -func (ab *AudioBuffer) availableLocked() int { - if ab.writePos >= ab.readPos { - return ab.writePos - ab.readPos - } - return ab.size - ab.readPos + ab.writePos -} ------------------ -------- pmostream/conversion.go ------ -package pmostream - -import ( - "encoding/binary" - "math" -) - -func convertFloat64ToFloat32(samples [][2]float64) []float32 { - if len(samples) == 0 { - return nil - } - result := make([]float32, len(samples)*2) - for i, s := range samples { - result[2*i] = float32(clamp(s[0], -1.0, 1.0)) - result[2*i+1] = float32(clamp(s[1], -1.0, 1.0)) - } - return result -} - -func convertFloat64ToPCM(samples [][2]float64) []byte { - if len(samples) == 0 { - return nil - } - buf := make([]byte, len(samples)*4) - for i, s := range samples { - l := int16(clamp(s[0], -1.0, 1.0) * 32767.0) - r := int16(clamp(s[1], -1.0, 1.0) * 32767.0) - binary.LittleEndian.PutUint16(buf[4*i:], uint16(uint16(l))) - binary.LittleEndian.PutUint16(buf[4*i+2:], uint16(uint16(r))) - } - return buf -} - -func float32ToPCM(samples []float32) []byte { - if len(samples) == 0 { - return nil - } - buf := make([]byte, len(samples)*2) - for i, v := range samples { - val := int16(clamp(float64(v), -1.0, 1.0) * 32767.0) - binary.LittleEndian.PutUint16(buf[2*i:], uint16(val)) - } - return buf -} - -func float32ToBytes(samples []float32) []byte { - if len(samples) == 0 { - return nil - } - buf := make([]byte, len(samples)*4) - for i, v := range samples { - binary.LittleEndian.PutUint32(buf[i*4:], math.Float32bits(v)) - } - return buf -} - -func bytesToFloat32(data []byte) []float32 { - if len(data)%4 != 0 { - return nil - } - result := make([]float32, len(data)/4) - for i := range result { - result[i] = math.Float32frombits(binary.LittleEndian.Uint32(data[i*4:])) - } - return result -} - -func pcmToFloat32(data []byte) []float32 { - if len(data)%2 != 0 { - return nil - } - result := make([]float32, len(data)/2) - for i := 0; i < len(result); i++ { - val := int16(binary.LittleEndian.Uint16(data[2*i:])) - result[i] = float32(val) / 32768.0 - } - return result -} - -func clamp(val, min, max float64) float64 { - if val < min { - return min - } - if val > max { - return max - } - return val -} ------------------ -------- pmostream/core.go ------ -package pmostream - -import ( - "fmt" - "math" - "sync" - "sync/atomic" - "time" - - "gargoton.petite-maison-orange.fr/eric/pmomusic/pmosoxr" - "github.com/gopxl/beep" - "github.com/gopxl/beep/effects" -) - -type SampleFormat int - -const ( - Float32 SampleFormat = iota - PCM16 -) - -type HiFiConfig struct { - TargetSampleRate beep.SampleRate - BufferSeconds int - ChunkSize int - ResampleQuality pmosoxr.Quality - Volume float64 - Format SampleFormat -} - -func DefaultHiFiConfig() HiFiConfig { - return HiFiConfig{ - TargetSampleRate: 48000, - BufferSeconds: 5, - ChunkSize: 1024, - ResampleQuality: pmosoxr.HQ, - Volume: 0.0, - Format: PCM16, - } -} - -type AudioProcessor struct { - config HiFiConfig - streamer beep.Streamer - format beep.Format - resampler *pmosoxr.Resampler - volume *effects.Volume - volumeValue float64 - buffer *AudioBuffer - masterBuffer *MasterBuffer - processMutex sync.Mutex - running atomic.Bool - wg sync.WaitGroup - resampleBuf []float32 - volumeMu sync.Mutex - streamDone atomic.Bool -} - -func NewAudioProcessor(streamer beep.Streamer, format beep.Format, config HiFiConfig, master *MasterBuffer) (*AudioProcessor, error) { - if streamer == nil && master == nil { - return nil, fmt.Errorf("streamer cannot be nil if no master buffer is provided") - } - - if format.NumChannels != 2 { - return nil, fmt.Errorf("only stereo format is supported") - } - - var vol *effects.Volume - if streamer != nil { - vol = &effects.Volume{ - Streamer: streamer, - Base: 2, - Volume: config.Volume, - Silent: false, - } - } - - var resampler *pmosoxr.Resampler - var err error - if streamer != nil && format.SampleRate != config.TargetSampleRate { - resampler, err = pmosoxr.New(float64(format.SampleRate), float64(config.TargetSampleRate), 2, config.ResampleQuality) - if err != nil { - return nil, fmt.Errorf("failed to create resampler: %w", err) - } - } - - sampleSize := 4 - if config.Format == PCM16 { - sampleSize = 2 - } - bytesPerSecond := int(config.TargetSampleRate) * sampleSize * 2 // stéréo - bufferSize := (bytesPerSecond * config.BufferSeconds) / config.ChunkSize - if bufferSize < 1 { - bufferSize = 1 - } - - ap := &AudioProcessor{ - config: config, - streamer: streamer, - format: format, - resampler: resampler, - volume: vol, - volumeValue: config.Volume, - buffer: NewAudioBuffer(bufferSize, config.Format), - masterBuffer: master, - } - ap.running.Store(true) - return ap, nil -} - -func (p *AudioProcessor) GetBuffer() *AudioBuffer { - return p.buffer -} - -func (p *AudioProcessor) SetVolume(volume float64) { - p.volumeMu.Lock() - defer p.volumeMu.Unlock() - p.volumeValue = volume - if p.volume != nil { - p.volume.Volume = volume - } -} - -func (p *AudioProcessor) Stop() { - p.running.Store(false) -} - -func (p *AudioProcessor) Close() error { - p.Stop() - p.wg.Wait() - p.processMutex.Lock() - defer p.processMutex.Unlock() - - if p.resampler != nil { - p.resampler.Delete() - } - if closer, ok := p.streamer.(interface{ Close() error }); ok { - return closer.Close() - } - return nil -} - -// Process lit depuis le streamer ou le master buffer, applique resampling + volume et écrit dans le buffer -func (p *AudioProcessor) Process() error { - if !p.running.Load() { - return nil - } - - p.wg.Add(1) - defer p.wg.Done() - - chunkSize := p.config.ChunkSize - if chunkSize <= 0 { - chunkSize = 1024 - } - - for p.running.Load() { - var samples [][2]float64 - - // 1) Lire depuis le streamer - if p.streamer != nil { - samples = make([][2]float64, chunkSize) - n, ok := p.streamer.Stream(samples) - if !ok { - p.streamDone.Store(true) - break - } - samples = samples[:n] - if n == 0 { - time.Sleep(5 * time.Millisecond) - continue - } - } else if p.masterBuffer != nil { - // Lecture via ForkedBuffer - chunks := p.masterBuffer.ReadAll() - if len(chunks) == 0 { - time.Sleep(5 * time.Millisecond) - continue - } - - samples = make([][2]float64, 0) - for _, c := range chunks { - var fs []float32 - if p.config.Format == Float32 { - fs = bytesToFloat32(c) - } else { - fs = pcmToFloat32(c) - } - if len(fs)%2 != 0 { - continue - } - for i := 0; i < len(fs); i += 2 { - samples = append(samples, [2]float64{float64(fs[i]), float64(fs[i+1])}) - } - } - if len(samples) == 0 { - time.Sleep(5 * time.Millisecond) - continue - } - } else { - time.Sleep(5 * time.Millisecond) - continue - } - - // 2) Resampler si nécessaire - var processed []float32 - if p.resampler != nil { - if len(p.resampleBuf) < len(samples)*2 { - p.resampleBuf = make([]float32, len(samples)*2) - } - inBuf := convertFloat64ToFloat32(samples) - _, np, err := p.resampler.Process(inBuf, p.resampleBuf) - if err != nil { - return err - } - processed = p.resampleBuf[:np] - } else { - processed = convertFloat64ToFloat32(samples) - } - - // 3) Appliquer volume - p.volumeMu.Lock() - volumeFactor := float32(math.Pow(2, p.volumeValue)) - p.volumeMu.Unlock() - for i := range processed { - processed[i] *= volumeFactor - } - - // 4) Convertir et écrire - var chunk []byte - if p.config.Format == Float32 { - chunk = float32ToBytes(processed) - } else { - chunk = float32ToPCM(processed) - } - p.buffer.Write(chunk) - } - - // Flush resampler à la fin uniquement - if p.resampler != nil { - flushBuf := make([]float32, 4096) - for { - _, np, err := p.resampler.Process(nil, flushBuf) - if err != nil { - return err - } - if np == 0 { - break - } - - processed := flushBuf[:np] - p.volumeMu.Lock() - volumeFactor := float32(math.Pow(2, p.volumeValue)) - p.volumeMu.Unlock() - for i := range processed { - processed[i] *= volumeFactor - } - - var chunk []byte - if p.config.Format == Float32 { - chunk = float32ToBytes(processed) - } else { - chunk = float32ToPCM(processed) - } - p.buffer.Write(chunk) - } - } - - p.buffer.Close() // fermer uniquement à la fin - return nil -} ------------------ -------- pmostream/fork_eq_test.go ------ -//go:build cgo -// +build cgo - -package pmostream - -import ( - "math" - "testing" - "time" - - "github.com/gopxl/beep" -) - -// TestForkedEQ vérifie que chaque fork peut avoir son propre ParametricEQ appliqué -func TestAudioProcessorWithMasterBuffer(t *testing.T) { - stream := beep.StreamerFunc(func(samples [][2]float64) (n int, ok bool) { - for i := range samples { - v := 0.2 * math.Sin(2*math.Pi*440*float64(i)/44100.0) - samples[i][0] = v - samples[i][1] = v - } - return len(samples), true - }) - - format := beep.Format{SampleRate: 44100, NumChannels: 2, Precision: 2} - config := DefaultHiFiConfig() - master := NewMasterBuffer() - - proc, err := NewAudioProcessor(stream, format, config, master) - if err != nil { - t.Fatal(err) - } - - go proc.Process() - defer proc.Close() - - time.Sleep(50 * time.Millisecond) - - if proc.buffer.Available() == 0 { - t.Fatal("buffer should contain data") - } - - chunk := proc.buffer.Read() - if chunk == nil || len(chunk) == 0 { - t.Fatal("failed to read chunk from buffer") - } -} ------------------ -------- pmostream/fork.go ------ -package pmostream - -import ( - "fmt" - "sync" - "time" - - "github.com/gopxl/beep" -) - -// MasterBuffer est un buffer central qui permet de fork un flux vers plusieurs processors -type MasterBuffer struct { - mu sync.RWMutex - cond *sync.Cond - chunks [][]byte - closed bool -} - -// NewMasterBuffer crée un buffer central -func NewMasterBuffer() *MasterBuffer { - mb := &MasterBuffer{} - mb.cond = sync.NewCond(&mb.mu) - return mb -} - -// Write ajoute un chunk au buffer central -func (mb *MasterBuffer) Write(chunk []byte) { - if len(chunk) == 0 { - return - } - - mb.mu.Lock() - defer mb.mu.Unlock() - - if mb.closed { - return - } - - data := make([]byte, len(chunk)) - copy(data, chunk) - - mb.chunks = append(mb.chunks, data) - mb.cond.Broadcast() -} - -// Fork crée un lecteur indépendant pour ce buffer -func (mb *MasterBuffer) Fork() *ForkedBuffer { - mb.mu.RLock() - defer mb.mu.RUnlock() - - return &ForkedBuffer{ - master: mb, - index: len(mb.chunks), - } -} - -// Close ferme le buffer et notifie tous les lecteurs -func (mb *MasterBuffer) Close() { - mb.mu.Lock() - defer mb.mu.Unlock() - mb.closed = true - mb.cond.Broadcast() -} - -// ForkedBuffer permet à un processor forké de lire indépendamment -type ForkedBuffer struct { - master *MasterBuffer - index int -} - -func (fb *ForkedBuffer) ReadAll() [][]byte { - fb.master.mu.Lock() // Lock au lieu de RLock - defer fb.master.mu.Unlock() - - if fb.index >= len(fb.master.chunks) { - return nil - } - - result := make([][]byte, len(fb.master.chunks)-fb.index) - for i := fb.index; i < len(fb.master.chunks); i++ { - result[i-fb.index] = fb.master.chunks[i] - } - fb.index = len(fb.master.chunks) - return result -} - -func (fb *ForkedBuffer) WaitForData(timeoutMs int) bool { - deadline := time.Now().Add(time.Duration(timeoutMs) * time.Millisecond) - fb.master.mu.Lock() - defer fb.master.mu.Unlock() - - for fb.index >= len(fb.master.chunks) && !fb.master.closed { - remaining := time.Until(deadline) - if remaining <= 0 { - return false - } - fb.master.cond.Wait() - } - return fb.index < len(fb.master.chunks) -} - -// ForkStreamer crée plusieurs streamers à partir d'un streamer source en utilisant un MasterBuffer -func ForkStreamer(streamer beep.Streamer, format beep.Format, config HiFiConfig, nForks int) ([]beep.Streamer, error) { - if nForks < 1 { - return nil, fmt.Errorf("nForks must be at least 1") - } - - // Créer un MasterBuffer - master := NewMasterBuffer() - - // Créer un processeur principal qui alimente le MasterBuffer - mainProc, err := NewAudioProcessor(streamer, format, config, master) - if err != nil { - return nil, err - } - - // Démarrer le traitement principal - go mainProc.Process() - - // Créer des streamers forké - forks := make([]beep.Streamer, nForks) - for i := 0; i < nForks; i++ { - forkedBuffer := master.Fork() - forks[i] = &forkedStreamer{ - fb: forkedBuffer, - config: config, - } - } - - return forks, nil -} - -// forkedStreamer implémente beep.Streamer pour lire depuis un ForkedBuffer -type forkedStreamer struct { - fb *ForkedBuffer - config HiFiConfig -} - -func (fs *forkedStreamer) Stream(samples [][2]float64) (n int, ok bool) { - if !fs.fb.WaitForData(100) { - return 0, true - } - - chunks := fs.fb.ReadAll() - if len(chunks) == 0 { - return 0, true - } - - // Concaténer tous les chunks - var totalSize int - for _, chunk := range chunks { - totalSize += len(chunk) - } - - combined := make([]byte, 0, totalSize) - for _, chunk := range chunks { - combined = append(combined, chunk...) - } - - // Convertir en float32 selon le format - var allData []float32 - if fs.config.Format == Float32 { - allData = bytesToFloat32(combined) - } else { - allData = pcmToFloat32(combined) - } - - if allData == nil { - return 0, true - } - - numSamples := len(allData) / 2 - if numSamples > len(samples) { - numSamples = len(samples) - } - - for i := 0; i < numSamples; i++ { - if 2*i+1 < len(allData) { - samples[i][0] = float64(allData[2*i]) - samples[i][1] = float64(allData[2*i+1]) - } - } - - return numSamples, true -} - -func (fs *forkedStreamer) Err() error { - return nil -} - -// ReadAll retourne tous les chunks disponibles dans le buffer central -func (mb *MasterBuffer) ReadAll() [][]byte { - mb.mu.RLock() - defer mb.mu.RUnlock() - - if mb.closed || len(mb.chunks) == 0 { - return nil - } - - // Créer une copie de tous les chunks - result := make([][]byte, len(mb.chunks)) - for i, chunk := range mb.chunks { - result[i] = make([]byte, len(chunk)) - copy(result[i], chunk) - } - - return result -} ------------------ -------- pmostream/parameq.go ------ -package pmostream - -import ( - "math" - "sync" - - "github.com/gopxl/beep" -) - -// ParametricEQ applique un égaliseur paramétrique stéréo (Biquad peaking) sur un Streamer. -type ParametricEQ struct { - input beep.Streamer - sampleRate float64 - mu sync.Mutex - - // Coefficients Biquad - a0, a1, a2, b1, b2 float64 - - // États pour les deux canaux - x1, x2, y1, y2 [2]float64 -} - -// EQParams définit les paramètres d'un filtre peaking -type EQParams struct { - FreqHz float64 // fréquence centrale en Hz - GainDB float64 // gain en dB - Q float64 // facteur de qualité -} - -// NewParametricEQ construit un EQ peaking stéréo en interrogeant le streamer pour la fréquence -func NewParametricEQ(input beep.Streamer, params EQParams, sr beep.SampleRate) *ParametricEQ { - eq := &ParametricEQ{ - input: input, - sampleRate: float64(sr), - } - - eq.setParams(params) - return eq -} - -// setParams calcule les coefficients du Biquad -func (eq *ParametricEQ) setParams(p EQParams) { - eq.mu.Lock() - defer eq.mu.Unlock() - - A := math.Pow(10, p.GainDB/40) // conversion dB -> amplitude - w0 := 2 * math.Pi * p.FreqHz / eq.sampleRate - alpha := math.Sin(w0) / (2 * p.Q) - - a0 := 1 + alpha/A - eq.a0 = 1 - eq.a1 = -2 * math.Cos(w0) / a0 - eq.a2 = (1 - alpha/A) / a0 - eq.b1 = 2 * math.Cos(w0) * -1 / a0 - eq.b2 = (1 - alpha*A) / a0 -} - -// Stream applique l'EQ sur un chunk stéréo float64 [][2]float64 -func (eq *ParametricEQ) Stream(samples [][2]float64) (n int, ok bool) { - eq.mu.Lock() - defer eq.mu.Unlock() - - if len(samples) == 0 { - return 0, true - } - - for i := range samples { - for ch := 0; ch < 2; ch++ { - x := samples[i][ch] - y := eq.a0*x + eq.a1*eq.x1[ch] + eq.a2*eq.x2[ch] - eq.b1*eq.y1[ch] - eq.b2*eq.y2[ch] - - eq.x2[ch] = eq.x1[ch] - eq.x1[ch] = x - eq.y2[ch] = eq.y1[ch] - eq.y1[ch] = y - - samples[i][ch] = y - } - } - return len(samples), true -} - -// Close libère les ressources (pas nécessaire ici mais pour interface uniforme) -func (eq *ParametricEQ) Close() error { - return nil -} - -// Wrap permet d'utiliser ParametricEQ comme beep.Streamer -func (eq *ParametricEQ) Streamer() beep.Streamer { - return beep.StreamerFunc(func(samples [][2]float64) (n int, ok bool) { - return eq.Stream(samples) - }) -} ------------------ -------- pmostream/streamer.go ------ -package pmostream - -import ( - "encoding/binary" - "log" - "net/http" - "sync" - "time" - - "github.com/gopxl/beep" -) - -// StreamManager gère plusieurs AudioProcessor et clients HTTP -type StreamManager struct { - processors map[string]*AudioProcessor - mu sync.RWMutex -} - -// NewStreamManager crée un gestionnaire de flux audio -func NewStreamManager() *StreamManager { - return &StreamManager{ - processors: make(map[string]*AudioProcessor), - } -} - -// AddProcessor ajoute un processeur audio et démarre sa boucle Process -func (m *StreamManager) AddProcessor(id string, processor *AudioProcessor) { - m.mu.Lock() - defer m.mu.Unlock() - - if _, exists := m.processors[id]; exists { - log.Printf("Processor with id %s already exists", id) - return - } - m.processors[id] = processor - - go func() { - if err := processor.Process(); err != nil { - log.Printf("Processor error for %s: %v", id, err) - } - }() -} - -// RemoveProcessor arrête et supprime un processeur audio -func (m *StreamManager) RemoveProcessor(id string) { - m.mu.Lock() - defer m.mu.Unlock() - - if processor, exists := m.processors[id]; exists { - processor.Stop() - processor.Close() - delete(m.processors, id) - } -} - -// GetHandler retourne un handler HTTP pour streamer un flux audio -func (m *StreamManager) GetHandler(id string) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - m.mu.RLock() - processor, exists := m.processors[id] - m.mu.RUnlock() - - if !exists { - http.Error(w, "Stream not found", http.StatusNotFound) - return - } - - buffer := processor.GetBuffer() - config := processor.config - - w.Header().Set("Content-Type", "audio/wav") - w.Header().Set("Cache-Control", "no-cache") - w.Header().Set("Connection", "keep-alive") - w.Header().Set("Access-Control-Allow-Origin", "*") - - flusher, ok := w.(http.Flusher) - if !ok { - http.Error(w, "Streaming not supported", http.StatusInternalServerError) - return - } - - // Écrire l'en-tête WAV pour streaming - if err := writeWavHeader(w, config.TargetSampleRate, config.Format); err != nil { - log.Printf("Failed to write WAV header: %v", err) - return - } - flusher.Flush() - - clientDone := r.Context().Done() - - for { - select { - case <-clientDone: - log.Printf("Client disconnected: %s", id) - return - default: - } - - // Attendre les données avec timeout - if !buffer.WaitForData(1, 100*time.Millisecond) { - continue - } - - chunk := buffer.Read() - if chunk == nil { - continue - } - - // Envoyer le chunk au client - if _, err := w.Write(chunk); err != nil { - log.Printf("Write error: %v", err) - return - } - flusher.Flush() - } - } -} - -// writeWavHeader écrit un en-tête WAV pour streaming -func writeWavHeader(w http.ResponseWriter, sampleRate beep.SampleRate, format SampleFormat) error { - var audioFormat uint16 = 1 // PCM - var bitsPerSample uint16 = 16 - - if format == Float32 { - audioFormat = 3 // IEEE_FLOAT - bitsPerSample = 32 - } - - numChannels := uint16(2) - blockAlign := numChannels * bitsPerSample / 8 - byteRate := uint32(sampleRate) * uint32(blockAlign) - - header := make([]byte, 44) - copy(header[0:4], "RIFF") - binary.LittleEndian.PutUint32(header[4:8], 0xFFFFFFFF) // Taille inconnue pour streaming - copy(header[8:12], "WAVE") - copy(header[12:16], "fmt ") - binary.LittleEndian.PutUint32(header[16:20], 16) - binary.LittleEndian.PutUint16(header[20:22], audioFormat) - binary.LittleEndian.PutUint16(header[22:24], numChannels) - binary.LittleEndian.PutUint32(header[24:28], uint32(sampleRate)) - binary.LittleEndian.PutUint32(header[28:32], byteRate) - binary.LittleEndian.PutUint16(header[32:34], blockAlign) - binary.LittleEndian.PutUint16(header[34:36], bitsPerSample) - copy(header[36:40], "data") - binary.LittleEndian.PutUint32(header[40:44], 0xFFFFFFFF) // Taille inconnue pour streaming - - _, err := w.Write(header) - return err -} ------------------ -============== Fin des sources des packages =============== -============== Analyse des bugs par chatgpt =============== diff --git a/cmd/pmomusic/main.go b/cmd/pmomusic/main.go deleted file mode 100644 index a7a3861a..00000000 --- a/cmd/pmomusic/main.go +++ /dev/null @@ -1,36 +0,0 @@ -package main - -import ( - "context" - "os/signal" - "syscall" - "time" - - log "github.com/sirupsen/logrus" - - "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp" - "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/mediarenderer" -) - -func main() { - log.SetLevel(log.DebugLevel) // → niveau debug - - ctx, stop := signal.NotifyContext( - context.Background(), - syscall.SIGINT, - syscall.SIGTERM, - ) - defer stop() - - // Crée le serveur avec baseURL auto-déduite depuis l’IP locale - server := pmoupnp.NewServer("pmomusic") - - server.RegisterDevice("", mediarenderer.FakeRenderer) - - if err := server.Run(ctx); err != nil { - log.Fatalf("server error: %v", err) - } - - time.Sleep(2 * time.Second) - -} diff --git a/fileutils/iswritable.go b/fileutils/iswritable.go deleted file mode 100644 index 1dac55f4..00000000 --- a/fileutils/iswritable.go +++ /dev/null @@ -1,27 +0,0 @@ -package fileutils - -import ( - "os" - "path/filepath" -) - -func IsWriteable(path string) bool { - info, err := os.Stat(path) - if err == nil { - // File exists, check owner write permission - return info.Mode().Perm()&0200 != 0 - } - if os.IsNotExist(err) { - // File does not exist, check if parent directory is writable - dir := filepath.Dir(path) - if dir == "" { - dir = "." // fallback - } - dirInfo, err := os.Stat(dir) - if err != nil { - return false - } - return dirInfo.IsDir() && dirInfo.Mode().Perm()&0200 != 0 - } - return false -} diff --git a/go.mod b/go.mod deleted file mode 100644 index 92eb9f8f..00000000 --- a/go.mod +++ /dev/null @@ -1,37 +0,0 @@ -module gargoton.petite-maison-orange.fr/eric/pmomusic - -go 1.24.2 - -require ( - github.com/beevik/etree v1.5.1 - github.com/globusdigital/soap v1.4.0 - github.com/google/uuid v1.6.0 - github.com/sirupsen/logrus v1.9.3 -) - -require ( - github.com/chai2010/webp v1.4.0 // indirect - github.com/disintegration/imaging v1.6.2 // indirect - github.com/dustin/go-humanize v1.0.1 // indirect - github.com/faiface/beep v1.1.0 // indirect - github.com/gopxl/beep v1.4.1 - github.com/hajimehoshi/go-mp3 v0.3.4 // indirect - github.com/icza/bitio v1.1.0 // indirect - github.com/jfreymuth/oggvorbis v1.0.5 // indirect - github.com/jfreymuth/vorbis v1.0.2 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-sqlite3 v1.14.32 // indirect - github.com/mewkiz/flac v1.0.8 // indirect - github.com/mewkiz/pkg v0.0.0-20230226050401-4010bf0fec14 // indirect - github.com/ncruces/go-strftime v0.1.9 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect - golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect - golang.org/x/image v0.31.0 // indirect - golang.org/x/sys v0.34.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect - modernc.org/libc v1.66.3 // indirect - modernc.org/mathutil v1.7.1 // indirect - modernc.org/memory v1.11.0 // indirect - modernc.org/sqlite v1.38.2 // indirect -) diff --git a/go.sum b/go.sum deleted file mode 100644 index 50640270..00000000 --- a/go.sum +++ /dev/null @@ -1,141 +0,0 @@ -github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= -github.com/beevik/etree v1.5.1 h1:TC3zyxYp+81wAmbsi8SWUpZCurbxa6S8RITYRSkNRwo= -github.com/beevik/etree v1.5.1/go.mod h1:gPNJNaBGVZ9AwsidazFZyygnd+0pAU38N4D+WemwKNs= -github.com/chai2010/webp v1.4.0 h1:6DA2pkkRUPnbOHvvsmGI3He1hBKf/bkRlniAiSGuEko= -github.com/chai2010/webp v1.4.0/go.mod h1:0XVwvZWdjjdxpUEIf7b9g9VkHFnInUSYujwqTLEuldU= -github.com/d4l3k/messagediff v1.2.2-0.20190829033028-7e0a312ae40b/go.mod h1:Oozbb1TVXFac9FtSIxHBMnBCq2qeH/2KkEQxENCrlLo= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c= -github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4= -github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= -github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= -github.com/faiface/beep v1.1.0 h1:A2gWP6xf5Rh7RG/p9/VAW2jRSDEGQm5sbOb38sf5d4c= -github.com/faiface/beep v1.1.0/go.mod h1:6I8p6kK2q4opL/eWb+kAkk38ehnTunWeToJB+s51sT4= -github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= -github.com/gdamore/tcell v1.3.0/go.mod h1:Hjvr+Ofd+gLglo7RYKxxnzCBmev3BzsS67MebKS4zMM= -github.com/globusdigital/soap v1.4.0 h1:nQDpWelZr3zKg6Oe1e5SqWd4PfiUvsl5/44oWUXy3II= -github.com/globusdigital/soap v1.4.0/go.mod h1:p8hjOZ4FmK0jXBTcIZ6e5M2QBfcsxBUKWBYsHM2eZRw= -github.com/go-audio/audio v1.0.0/go.mod h1:6uAu0+H2lHkwdGsAY+j2wHPNPpPoeg5AaEFh9FlA+Zs= -github.com/go-audio/riff v1.0.0/go.mod h1:l3cQwc85y79NQFCRB7TiPoNiaijp6q8Z0Uv38rVG498= -github.com/go-audio/wav v1.0.0/go.mod h1:3yoReyQOsiARkvPl3ERCi8JFjihzG6WhjYpZCf5zAWE= -github.com/go-audio/wav v1.1.0/go.mod h1:mpe9qfwbScEbkd8uybLuIpTgHyrISw/OTuvjUW2iGtE= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gopxl/beep v1.4.1 h1:WqNs9RsDAhG9M3khMyc1FaVY50dTdxG/6S6a3qsUHqE= -github.com/gopxl/beep v1.4.1/go.mod h1:A1dmiUkuY8kxsvcNJNUBIEcchmiP6eUyCHSxpXl0YO0= -github.com/hajimehoshi/go-mp3 v0.3.0 h1:fTM5DXjp/DL2G74HHAs/aBGiS9Tg7wnp+jkU38bHy4g= -github.com/hajimehoshi/go-mp3 v0.3.0/go.mod h1:qMJj/CSDxx6CGHiZeCgbiq2DSUkbK0UbtXShQcnfyMM= -github.com/hajimehoshi/go-mp3 v0.3.4 h1:NUP7pBYH8OguP4diaTZ9wJbUbk3tC0KlfzsEpWmYj68= -github.com/hajimehoshi/go-mp3 v0.3.4/go.mod h1:fRtZraRFcWb0pu7ok0LqyFhCUrPeMsGRSVop0eemFmo= -github.com/hajimehoshi/oto v0.6.1/go.mod h1:0QXGEkbuJRohbJaxr7ZQSxnju7hEhseiPx2hrh6raOI= -github.com/hajimehoshi/oto v0.7.1/go.mod h1:wovJ8WWMfFKvP587mhHgot/MBr4DnNy9m6EepeVGnos= -github.com/hajimehoshi/oto/v2 v2.3.1/go.mod h1:seWLbgHH7AyUMYKfKYT9pg7PhUu9/SisyJvNTT+ASQo= -github.com/icza/bitio v1.0.0 h1:squ/m1SHyFeCA6+6Gyol1AxV9nmPPlJFT8c2vKdj3U8= -github.com/icza/bitio v1.0.0/go.mod h1:0jGnlLAx8MKMr9VGnn/4YrvZiprkvBelsVIbA9Jjr9A= -github.com/icza/bitio v1.1.0 h1:ysX4vtldjdi3Ygai5m1cWy4oLkhWTAi+SyO6HC8L9T0= -github.com/icza/bitio v1.1.0/go.mod h1:0jGnlLAx8MKMr9VGnn/4YrvZiprkvBelsVIbA9Jjr9A= -github.com/icza/mighty v0.0.0-20180919140131-cfd07d671de6/go.mod h1:xQig96I1VNBDIWGCdTt54nHt6EeI639SmHycLYL7FkA= -github.com/jfreymuth/oggvorbis v1.0.1 h1:NT0eXBgE2WHzu6RT/6zcb2H10Kxj6Fm3PccT0LE6bqw= -github.com/jfreymuth/oggvorbis v1.0.1/go.mod h1:NqS+K+UXKje0FUYUPosyQ+XTVvjmVjps1aEZH1sumIk= -github.com/jfreymuth/oggvorbis v1.0.5 h1:u+Ck+R0eLSRhgq8WTmffYnrVtSztJcYrl588DM4e3kQ= -github.com/jfreymuth/oggvorbis v1.0.5/go.mod h1:1U4pqWmghcoVsCJJ4fRBKv9peUJMBHixthRlBeD6uII= -github.com/jfreymuth/vorbis v1.0.0 h1:SmDf783s82lIjGZi8EGUUaS7YxPHgRj4ZXW/h7rUi7U= -github.com/jfreymuth/vorbis v1.0.0/go.mod h1:8zy3lUAm9K/rJJk223RKy6vjCZTWC61NA2QD06bfOE0= -github.com/jfreymuth/vorbis v1.0.2 h1:m1xH6+ZI4thH927pgKD8JOH4eaGRm18rEE9/0WKjvNE= -github.com/jfreymuth/vorbis v1.0.2/go.mod h1:DoftRo4AznKnShRl1GxiTFCseHr4zR9BN3TWXyuzrqQ= -github.com/jszwec/csvutil v1.5.1/go.mod h1:Rpu7Uu9giO9subDyMCIQfHVDuLrcaC36UA4YcJjGBkg= -github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-sqlite3 v1.14.32 h1:JD12Ag3oLy1zQA+BNn74xRgaBbdhbNIDYvQUEuuErjs= -github.com/mattn/go-sqlite3 v1.14.32/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= -github.com/mewkiz/flac v1.0.7 h1:uIXEjnuXqdRaZttmSFM5v5Ukp4U6orrZsnYGGR3yow8= -github.com/mewkiz/flac v1.0.7/go.mod h1:yU74UH277dBUpqxPouHSQIar3G1X/QIclVbFahSd1pU= -github.com/mewkiz/flac v1.0.8 h1:cophRjvafteDGmqsfXRK28YAX6l8wy19QxTHruEEg1s= -github.com/mewkiz/flac v1.0.8/go.mod h1:l7dt5uFY724eKVkHQtAJAQSkhpC3helU3RDxN0ESAqo= -github.com/mewkiz/pkg v0.0.0-20190919212034-518ade7978e2 h1:EyTNMdePWaoWsRSGQnXiSoQu0r6RS1eA557AwJhlzHU= -github.com/mewkiz/pkg v0.0.0-20190919212034-518ade7978e2/go.mod h1:3E2FUC/qYUfM8+r9zAwpeHJzqRVVMIYnpzD/clwWxyA= -github.com/mewkiz/pkg v0.0.0-20230226050401-4010bf0fec14 h1:tnAPMExbRERsyEYkmR1YjhTgDM0iqyiBYf8ojRXxdbA= -github.com/mewkiz/pkg v0.0.0-20230226050401-4010bf0fec14/go.mod h1:QYCFBiH5q6XTHEbWhR0uhR3M9qNPoD2CSQzr0g75kE4= -github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= -github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= -github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o= -golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8= -golang.org/x/image v0.0.0-20190220214146-31aff87c08e9/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 h1:hVwzHzIUGRjiF7EcUjqNxk3NCfkPxbDKRdnNE1Rpg0U= -golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20211028202545-6944b10bf410 h1:hTftEOvwiOq2+O8k2D5/Q7COC7k5Qcrgc2TFURJYnvQ= -golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= -golang.org/x/image v0.5.0/go.mod h1:FVC7BI/5Ym8R25iw5OLsgshdUBbT1h5jZTpA+mvAdZ4= -golang.org/x/image v0.31.0 h1:mLChjE2MV6g1S7oqbXC0/UcKijjm5fnJLUYKIYrLESA= -golang.org/x/image v0.31.0/go.mod h1:R9ec5Lcp96v9FTF+ajwaH3uGxPH4fKfHHAVbUILxghA= -golang.org/x/mobile v0.0.0-20190415191353-3e0bab5405d6/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190429190828-d89cdac9e872/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220712014510-0a85c31ab51e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= -golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= -golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -modernc.org/libc v1.66.3 h1:cfCbjTUcdsKyyZZfEUKfoHcP3S0Wkvz3jgSzByEWVCQ= -modernc.org/libc v1.66.3/go.mod h1:XD9zO8kt59cANKvHPXpx7yS2ELPheAey0vjIuZOhOU8= -modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= -modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg= -modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI= -modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw= -modernc.org/sqlite v1.38.2 h1:Aclu7+tgjgcQVShZqim41Bbw9Cho0y/7WzYptXqkEek= -modernc.org/sqlite v1.38.2/go.mod h1:cPTJYSlgg3Sfg046yBShXENNtPrWrDX8bsbAQBzgQ5E= diff --git a/netutils/ip_detect.go b/netutils/ip_detect.go deleted file mode 100644 index 90e3c8c3..00000000 --- a/netutils/ip_detect.go +++ /dev/null @@ -1,17 +0,0 @@ -package netutils - -import ( - "net" -) - -// Fonction helper (remplace votre netutils.GuessLocalIP) -func GuessLocalIP() (string, error) { - conn, err := net.Dial("udp", "8.8.8.8:80") - if err != nil { - return "127.0.0.1", nil - } - defer conn.Close() - - localAddr := conn.LocalAddr().(*net.UDPAddr) - return localAddr.IP.String(), nil -} diff --git a/netutils/list_all_ip.go b/netutils/list_all_ip.go deleted file mode 100644 index 19240745..00000000 --- a/netutils/list_all_ip.go +++ /dev/null @@ -1,49 +0,0 @@ -package netutils - -import ( - "net" -) - -// ListAllIPs returns a map of interface names to their associated IPv4 addresses. -func ListAllIPs() map[string][]string { - result := make(map[string][]string) - - ifaces, err := net.Interfaces() - if err != nil { - result["error"] = []string{err.Error()} - return result - } - - for _, iface := range ifaces { - if iface.Flags&net.FlagUp == 0 { - continue // Ignore down interfaces - } - - addrs, err := iface.Addrs() - if err != nil { - continue - } - - var ips []string - for _, addr := range addrs { - var ip net.IP - switch v := addr.(type) { - case *net.IPNet: - ip = v.IP - case *net.IPAddr: - ip = v.IP - } - - if ip == nil || ip.To4() == nil || ip.IsLoopback() { - continue - } - ips = append(ips, ip.String()) - } - - if len(ips) > 0 { - result[iface.Name] = ips - } - } - - return result -} diff --git a/pmoapp/web.go b/pmoapp/web.go deleted file mode 100644 index c7f11c5e..00000000 --- a/pmoapp/web.go +++ /dev/null @@ -1,35 +0,0 @@ -package pmoapp - -import ( - "embed" - "io/fs" - "net/http" -) - -//go:embed web/dist/* -var AppRoot embed.FS - -func Handler(mux *http.ServeMux) { - fsys, _ := fs.Sub(AppRoot, "web/dist") - - // /app → page principale - mux.Handle("/app/", http.StripPrefix("/app/", http.FileServer(http.FS(fsys)))) - mux.HandleFunc("/app", func(w http.ResponseWriter, r *http.Request) { - index, _ := fs.ReadFile(fsys, "index.html") - w.Header().Set("Content-Type", "text/html; charset=utf-8") - w.Write(index) - }) - - // /log → interface log (React) - mux.Handle("/log/", http.StripPrefix("/log/", http.FileServer(http.FS(fsys)))) - mux.HandleFunc("/log", func(w http.ResponseWriter, r *http.Request) { - index, _ := fs.ReadFile(fsys, "index.html") - w.Header().Set("Content-Type", "text/html; charset=utf-8") - w.Write(index) - }) - - // / → redirect vers /app - mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - http.Redirect(w, r, "/app", http.StatusFound) - }) -} diff --git a/pmoapp/web/.gitignore b/pmoapp/web/.gitignore deleted file mode 100644 index a547bf36..00000000 --- a/pmoapp/web/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/pmoapp/web/README.md b/pmoapp/web/README.md deleted file mode 100644 index 7959ce42..00000000 --- a/pmoapp/web/README.md +++ /dev/null @@ -1,69 +0,0 @@ -# React + TypeScript + Vite - -This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. - -Currently, two official plugins are available: - -- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) for Fast Refresh -- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh - -## Expanding the ESLint configuration - -If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules: - -```js -export default tseslint.config([ - globalIgnores(['dist']), - { - files: ['**/*.{ts,tsx}'], - extends: [ - // Other configs... - - // Remove tseslint.configs.recommended and replace with this - ...tseslint.configs.recommendedTypeChecked, - // Alternatively, use this for stricter rules - ...tseslint.configs.strictTypeChecked, - // Optionally, add this for stylistic rules - ...tseslint.configs.stylisticTypeChecked, - - // Other configs... - ], - languageOptions: { - parserOptions: { - project: ['./tsconfig.node.json', './tsconfig.app.json'], - tsconfigRootDir: import.meta.dirname, - }, - // other options... - }, - }, -]) -``` - -You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules: - -```js -// eslint.config.js -import reactX from 'eslint-plugin-react-x' -import reactDom from 'eslint-plugin-react-dom' - -export default tseslint.config([ - globalIgnores(['dist']), - { - files: ['**/*.{ts,tsx}'], - extends: [ - // Other configs... - // Enable lint rules for React - reactX.configs['recommended-typescript'], - // Enable lint rules for React DOM - reactDom.configs.recommended, - ], - languageOptions: { - parserOptions: { - project: ['./tsconfig.node.json', './tsconfig.app.json'], - tsconfigRootDir: import.meta.dirname, - }, - // other options... - }, - }, -]) -``` diff --git a/pmoapp/web/eslint.config.js b/pmoapp/web/eslint.config.js deleted file mode 100644 index d94e7deb..00000000 --- a/pmoapp/web/eslint.config.js +++ /dev/null @@ -1,23 +0,0 @@ -import js from '@eslint/js' -import globals from 'globals' -import reactHooks from 'eslint-plugin-react-hooks' -import reactRefresh from 'eslint-plugin-react-refresh' -import tseslint from 'typescript-eslint' -import { globalIgnores } from 'eslint/config' - -export default tseslint.config([ - globalIgnores(['dist']), - { - files: ['**/*.{ts,tsx}'], - extends: [ - js.configs.recommended, - tseslint.configs.recommended, - reactHooks.configs['recommended-latest'], - reactRefresh.configs.vite, - ], - languageOptions: { - ecmaVersion: 2020, - globals: globals.browser, - }, - }, -]) diff --git a/pmoapp/web/index.html b/pmoapp/web/index.html deleted file mode 100644 index f078c018..00000000 --- a/pmoapp/web/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - PMO Log - - -
- - - diff --git a/pmoapp/web/package-lock.json b/pmoapp/web/package-lock.json deleted file mode 100644 index ea958e44..00000000 --- a/pmoapp/web/package-lock.json +++ /dev/null @@ -1,5869 +0,0 @@ -{ - "name": "web", - "version": "0.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "web", - "version": "0.0.0", - "dependencies": { - "@types/react-syntax-highlighter": "^15.5.13", - "he": "^1.2.0", - "react": "^19.1.1", - "react-dom": "^19.1.1", - "react-markdown": "^10.1.0", - "react-syntax-highlighter": "^15.6.6", - "rehype-raw": "^7.0.0" - }, - "devDependencies": { - "@eslint/js": "^9.33.0", - "@tailwindcss/postcss": "^4.1.13", - "@tailwindcss/typography": "^0.5.16", - "@types/he": "^1.2.3", - "@types/react": "^19.1.10", - "@types/react-dom": "^19.1.7", - "@vitejs/plugin-react": "^5.0.0", - "autoprefixer": "^10.4.21", - "eslint": "^9.33.0", - "eslint-plugin-react-hooks": "^5.2.0", - "eslint-plugin-react-refresh": "^0.4.20", - "globals": "^16.3.0", - "postcss": "^8.5.6", - "tailwindcss": "^4.1.13", - "typescript": "~5.8.3", - "typescript-eslint": "^8.39.1", - "vite": "^7.1.2" - } - }, - "node_modules/@alloc/quick-lru": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", - "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", - "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.27.1", - "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.4.tgz", - "integrity": "sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.4.tgz", - "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.3", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-module-transforms": "^7.28.3", - "@babel/helpers": "^7.28.4", - "@babel/parser": "^7.28.4", - "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.4", - "@babel/types": "^7.28.4", - "@jridgewell/remapping": "^2.3.5", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/generator": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", - "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.28.3", - "@babel/types": "^7.28.2", - "@jridgewell/gen-mapping": "^0.3.12", - "@jridgewell/trace-mapping": "^0.3.28", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", - "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.27.2", - "@babel/helper-validator-option": "^7.27.1", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-globals": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", - "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", - "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.28.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", - "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", - "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", - "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz", - "integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.28.4" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", - "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", - "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/runtime": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", - "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/template": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", - "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/parser": "^7.27.2", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.4.tgz", - "integrity": "sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.3", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.4", - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.4", - "debug": "^4.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz", - "integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz", - "integrity": "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.9.tgz", - "integrity": "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz", - "integrity": "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.9.tgz", - "integrity": "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz", - "integrity": "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz", - "integrity": "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz", - "integrity": "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz", - "integrity": "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz", - "integrity": "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz", - "integrity": "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz", - "integrity": "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz", - "integrity": "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz", - "integrity": "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz", - "integrity": "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz", - "integrity": "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz", - "integrity": "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz", - "integrity": "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz", - "integrity": "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz", - "integrity": "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz", - "integrity": "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz", - "integrity": "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz", - "integrity": "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz", - "integrity": "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz", - "integrity": "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz", - "integrity": "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz", - "integrity": "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", - "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", - "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/config-array": { - "version": "0.21.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", - "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/object-schema": "^2.1.6", - "debug": "^4.3.1", - "minimatch": "^3.1.2" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/config-helpers": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz", - "integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/core": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz", - "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@types/json-schema": "^7.0.15" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", - "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/js": { - "version": "9.35.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.35.0.tgz", - "integrity": "sha512-30iXE9whjlILfWobBkNerJo+TXYsgVM5ERQwMcMKCHckHflCmf7wXDAHlARoWnh0s1U72WqlbeyE7iAcCzuCPw==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - } - }, - "node_modules/@eslint/object-schema": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", - "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/plugin-kit": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz", - "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/core": "^0.15.2", - "levn": "^0.4.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@humanfs/core": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", - "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanfs/node": { - "version": "0.16.7", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", - "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@humanfs/core": "^0.19.1", - "@humanwhocodes/retry": "^0.4.0" - }, - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/retry": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", - "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@isaacs/fs-minipass": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", - "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.4" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/remapping": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", - "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.30", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz", - "integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.34.tgz", - "integrity": "sha512-LyAREkZHP5pMom7c24meKmJCdhf2hEyvam2q0unr3or9ydwDL+DJ8chTF6Av/RFPb3rH8UFBdMzO5MxTZW97oA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.50.1.tgz", - "integrity": "sha512-HJXwzoZN4eYTdD8bVV22DN8gsPCAj3V20NHKOs8ezfXanGpmVPR7kalUHd+Y31IJp9stdB87VKPFbsGY3H/2ag==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.50.1.tgz", - "integrity": "sha512-PZlsJVcjHfcH53mOImyt3bc97Ep3FJDXRpk9sMdGX0qgLmY0EIWxCag6EigerGhLVuL8lDVYNnSo8qnTElO4xw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.50.1.tgz", - "integrity": "sha512-xc6i2AuWh++oGi4ylOFPmzJOEeAa2lJeGUGb4MudOtgfyyjr4UPNK+eEWTPLvmPJIY/pgw6ssFIox23SyrkkJw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.50.1.tgz", - "integrity": "sha512-2ofU89lEpDYhdLAbRdeyz/kX3Y2lpYc6ShRnDjY35bZhd2ipuDMDi6ZTQ9NIag94K28nFMofdnKeHR7BT0CATw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.50.1.tgz", - "integrity": "sha512-wOsE6H2u6PxsHY/BeFHA4VGQN3KUJFZp7QJBmDYI983fgxq5Th8FDkVuERb2l9vDMs1D5XhOrhBrnqcEY6l8ZA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.50.1.tgz", - "integrity": "sha512-A/xeqaHTlKbQggxCqispFAcNjycpUEHP52mwMQZUNqDUJFFYtPHCXS1VAG29uMlDzIVr+i00tSFWFLivMcoIBQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.50.1.tgz", - "integrity": "sha512-54v4okehwl5TaSIkpp97rAHGp7t3ghinRd/vyC1iXqXMfjYUTm7TfYmCzXDoHUPTTf36L8pr0E7YsD3CfB3ZDg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.50.1.tgz", - "integrity": "sha512-p/LaFyajPN/0PUHjv8TNyxLiA7RwmDoVY3flXHPSzqrGcIp/c2FjwPPP5++u87DGHtw+5kSH5bCJz0mvXngYxw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.50.1.tgz", - "integrity": "sha512-2AbMhFFkTo6Ptna1zO7kAXXDLi7H9fGTbVaIq2AAYO7yzcAsuTNWPHhb2aTA6GPiP+JXh85Y8CiS54iZoj4opw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.50.1.tgz", - "integrity": "sha512-Cgef+5aZwuvesQNw9eX7g19FfKX5/pQRIyhoXLCiBOrWopjo7ycfB292TX9MDcDijiuIJlx1IzJz3IoCPfqs9w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.50.1.tgz", - "integrity": "sha512-RPhTwWMzpYYrHrJAS7CmpdtHNKtt2Ueo+BlLBjfZEhYBhK00OsEqM08/7f+eohiF6poe0YRDDd8nAvwtE/Y62Q==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.50.1.tgz", - "integrity": "sha512-eSGMVQw9iekut62O7eBdbiccRguuDgiPMsw++BVUg+1K7WjZXHOg/YOT9SWMzPZA+w98G+Fa1VqJgHZOHHnY0Q==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.50.1.tgz", - "integrity": "sha512-S208ojx8a4ciIPrLgazF6AgdcNJzQE4+S9rsmOmDJkusvctii+ZvEuIC4v/xFqzbuP8yDjn73oBlNDgF6YGSXQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.50.1.tgz", - "integrity": "sha512-3Ag8Ls1ggqkGUvSZWYcdgFwriy2lWo+0QlYgEFra/5JGtAd6C5Hw59oojx1DeqcA2Wds2ayRgvJ4qxVTzCHgzg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.50.1.tgz", - "integrity": "sha512-t9YrKfaxCYe7l7ldFERE1BRg/4TATxIg+YieHQ966jwvo7ddHJxPj9cNFWLAzhkVsbBvNA4qTbPVNsZKBO4NSg==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.50.1.tgz", - "integrity": "sha512-MCgtFB2+SVNuQmmjHf+wfI4CMxy3Tk8XjA5Z//A0AKD7QXUYFMQcns91K6dEHBvZPCnhJSyDWLApk40Iq/H3tA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.50.1.tgz", - "integrity": "sha512-nEvqG+0jeRmqaUMuwzlfMKwcIVffy/9KGbAGyoa26iu6eSngAYQ512bMXuqqPrlTyfqdlB9FVINs93j534UJrg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.50.1.tgz", - "integrity": "sha512-RDsLm+phmT3MJd9SNxA9MNuEAO/J2fhW8GXk62G/B4G7sLVumNFbRwDL6v5NrESb48k+QMqdGbHgEtfU0LCpbA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.50.1.tgz", - "integrity": "sha512-hpZB/TImk2FlAFAIsoElM3tLzq57uxnGYwplg6WDyAxbYczSi8O2eQ+H2Lx74504rwKtZ3N2g4bCUkiamzS6TQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.50.1.tgz", - "integrity": "sha512-SXjv8JlbzKM0fTJidX4eVsH+Wmnp0/WcD8gJxIZyR6Gay5Qcsmdbi9zVtnbkGPG8v2vMR1AD06lGWy5FLMcG7A==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.50.1.tgz", - "integrity": "sha512-StxAO/8ts62KZVRAm4JZYq9+NqNsV7RvimNK+YM7ry//zebEH6meuugqW/P5OFUCjyQgui+9fUxT6d5NShvMvA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@tailwindcss/node": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.13.tgz", - "integrity": "sha512-eq3ouolC1oEFOAvOMOBAmfCIqZBJuvWvvYWh5h5iOYfe1HFC6+GZ6EIL0JdM3/niGRJmnrOc+8gl9/HGUaaptw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/remapping": "^2.3.4", - "enhanced-resolve": "^5.18.3", - "jiti": "^2.5.1", - "lightningcss": "1.30.1", - "magic-string": "^0.30.18", - "source-map-js": "^1.2.1", - "tailwindcss": "4.1.13" - } - }, - "node_modules/@tailwindcss/oxide": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.13.tgz", - "integrity": "sha512-CPgsM1IpGRa880sMbYmG1s4xhAy3xEt1QULgTJGQmZUeNgXFR7s1YxYygmJyBGtou4SyEosGAGEeYqY7R53bIA==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "detect-libc": "^2.0.4", - "tar": "^7.4.3" - }, - "engines": { - "node": ">= 10" - }, - "optionalDependencies": { - "@tailwindcss/oxide-android-arm64": "4.1.13", - "@tailwindcss/oxide-darwin-arm64": "4.1.13", - "@tailwindcss/oxide-darwin-x64": "4.1.13", - "@tailwindcss/oxide-freebsd-x64": "4.1.13", - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.13", - "@tailwindcss/oxide-linux-arm64-gnu": "4.1.13", - "@tailwindcss/oxide-linux-arm64-musl": "4.1.13", - "@tailwindcss/oxide-linux-x64-gnu": "4.1.13", - "@tailwindcss/oxide-linux-x64-musl": "4.1.13", - "@tailwindcss/oxide-wasm32-wasi": "4.1.13", - "@tailwindcss/oxide-win32-arm64-msvc": "4.1.13", - "@tailwindcss/oxide-win32-x64-msvc": "4.1.13" - } - }, - "node_modules/@tailwindcss/oxide-android-arm64": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.13.tgz", - "integrity": "sha512-BrpTrVYyejbgGo57yc8ieE+D6VT9GOgnNdmh5Sac6+t0m+v+sKQevpFVpwX3pBrM2qKrQwJ0c5eDbtjouY/+ew==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-darwin-arm64": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.13.tgz", - "integrity": "sha512-YP+Jksc4U0KHcu76UhRDHq9bx4qtBftp9ShK/7UGfq0wpaP96YVnnjFnj3ZFrUAjc5iECzODl/Ts0AN7ZPOANQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-darwin-x64": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.13.tgz", - "integrity": "sha512-aAJ3bbwrn/PQHDxCto9sxwQfT30PzyYJFG0u/BWZGeVXi5Hx6uuUOQEI2Fa43qvmUjTRQNZnGqe9t0Zntexeuw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-freebsd-x64": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.13.tgz", - "integrity": "sha512-Wt8KvASHwSXhKE/dJLCCWcTSVmBj3xhVhp/aF3RpAhGeZ3sVo7+NTfgiN8Vey/Fi8prRClDs6/f0KXPDTZE6nQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.13.tgz", - "integrity": "sha512-mbVbcAsW3Gkm2MGwA93eLtWrwajz91aXZCNSkGTx/R5eb6KpKD5q8Ueckkh9YNboU8RH7jiv+ol/I7ZyQ9H7Bw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.13.tgz", - "integrity": "sha512-wdtfkmpXiwej/yoAkrCP2DNzRXCALq9NVLgLELgLim1QpSfhQM5+ZxQQF8fkOiEpuNoKLp4nKZ6RC4kmeFH0HQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm64-musl": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.13.tgz", - "integrity": "sha512-hZQrmtLdhyqzXHB7mkXfq0IYbxegaqTmfa1p9MBj72WPoDD3oNOh1Lnxf6xZLY9C3OV6qiCYkO1i/LrzEdW2mg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-x64-gnu": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.13.tgz", - "integrity": "sha512-uaZTYWxSXyMWDJZNY1Ul7XkJTCBRFZ5Fo6wtjrgBKzZLoJNrG+WderJwAjPzuNZOnmdrVg260DKwXCFtJ/hWRQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-linux-x64-musl": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.13.tgz", - "integrity": "sha512-oXiPj5mi4Hdn50v5RdnuuIms0PVPI/EG4fxAfFiIKQh5TgQgX7oSuDWntHW7WNIi/yVLAiS+CRGW4RkoGSSgVQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.13.tgz", - "integrity": "sha512-+LC2nNtPovtrDwBc/nqnIKYh/W2+R69FA0hgoeOn64BdCX522u19ryLh3Vf3F8W49XBcMIxSe665kwy21FkhvA==", - "bundleDependencies": [ - "@napi-rs/wasm-runtime", - "@emnapi/core", - "@emnapi/runtime", - "@tybys/wasm-util", - "@emnapi/wasi-threads", - "tslib" - ], - "cpu": [ - "wasm32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "^1.4.5", - "@emnapi/runtime": "^1.4.5", - "@emnapi/wasi-threads": "^1.0.4", - "@napi-rs/wasm-runtime": "^0.2.12", - "@tybys/wasm-util": "^0.10.0", - "tslib": "^2.8.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.13.tgz", - "integrity": "sha512-dziTNeQXtoQ2KBXmrjCxsuPk3F3CQ/yb7ZNZNA+UkNTeiTGgfeh+gH5Pi7mRncVgcPD2xgHvkFCh/MhZWSgyQg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/oxide-win32-x64-msvc": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.13.tgz", - "integrity": "sha512-3+LKesjXydTkHk5zXX01b5KMzLV1xl2mcktBJkje7rhFUpUlYJy7IMOLqjIRQncLTa1WZZiFY/foAeB5nmaiTw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tailwindcss/postcss": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.13.tgz", - "integrity": "sha512-HLgx6YSFKJT7rJqh9oJs/TkBFhxuMOfUKSBEPYwV+t78POOBsdQ7crhZLzwcH3T0UyUuOzU/GK5pk5eKr3wCiQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@alloc/quick-lru": "^5.2.0", - "@tailwindcss/node": "4.1.13", - "@tailwindcss/oxide": "4.1.13", - "postcss": "^8.4.41", - "tailwindcss": "4.1.13" - } - }, - "node_modules/@tailwindcss/typography": { - "version": "0.5.16", - "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.16.tgz", - "integrity": "sha512-0wDLwCVF5V3x3b1SGXPCDcdsbDHMBe+lkFzBRaHeLvNi+nrrnZ1lA18u+OTWO8iSWU2GxUOCvlXtDuqftc1oiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "lodash.castarray": "^4.4.0", - "lodash.isplainobject": "^4.0.6", - "lodash.merge": "^4.6.2", - "postcss-selector-parser": "6.0.10" - }, - "peerDependencies": { - "tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1" - } - }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", - "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", - "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.28.2" - } - }, - "node_modules/@types/debug": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", - "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", - "license": "MIT", - "dependencies": { - "@types/ms": "*" - } - }, - "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "license": "MIT" - }, - "node_modules/@types/estree-jsx": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", - "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", - "license": "MIT", - "dependencies": { - "@types/estree": "*" - } - }, - "node_modules/@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "license": "MIT", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/@types/he": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@types/he/-/he-1.2.3.tgz", - "integrity": "sha512-q67/qwlxblDzEDvzHhVkwc1gzVWxaNxeyHUBF4xElrvjL11O+Ytze+1fGpBHlr/H9myiBUaUXNnNPmBHxxfAcA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/mdast": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", - "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", - "license": "MIT", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/@types/ms": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", - "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", - "license": "MIT" - }, - "node_modules/@types/react": { - "version": "19.1.12", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.12.tgz", - "integrity": "sha512-cMoR+FoAf/Jyq6+Df2/Z41jISvGZZ2eTlnsaJRptmZ76Caldwy1odD4xTr/gNV9VLj0AWgg/nmkevIyUfIIq5w==", - "license": "MIT", - "dependencies": { - "csstype": "^3.0.2" - } - }, - "node_modules/@types/react-dom": { - "version": "19.1.9", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.9.tgz", - "integrity": "sha512-qXRuZaOsAdXKFyOhRBg6Lqqc0yay13vN7KrIg4L7N4aaHN68ma9OK3NE1BoDFgFOTfM7zg+3/8+2n8rLUH3OKQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "@types/react": "^19.0.0" - } - }, - "node_modules/@types/react-syntax-highlighter": { - "version": "15.5.13", - "resolved": "https://registry.npmjs.org/@types/react-syntax-highlighter/-/react-syntax-highlighter-15.5.13.tgz", - "integrity": "sha512-uLGJ87j6Sz8UaBAooU0T6lWJ0dBmjZgN1PZTrj05TNql2/XpC6+4HhMT5syIdFUUt+FASfCeLLv4kBygNU+8qA==", - "license": "MIT", - "dependencies": { - "@types/react": "*" - } - }, - "node_modules/@types/unist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", - "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", - "license": "MIT" - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.42.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.42.0.tgz", - "integrity": "sha512-Aq2dPqsQkxHOLfb2OPv43RnIvfj05nw8v/6n3B2NABIPpHnjQnaLo9QGMTvml+tv4korl/Cjfrb/BYhoL8UUTQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.42.0", - "@typescript-eslint/type-utils": "8.42.0", - "@typescript-eslint/utils": "8.42.0", - "@typescript-eslint/visitor-keys": "8.42.0", - "graphemer": "^1.4.0", - "ignore": "^7.0.0", - "natural-compare": "^1.4.0", - "ts-api-utils": "^2.1.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^8.42.0", - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", - "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "8.42.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.42.0.tgz", - "integrity": "sha512-r1XG74QgShUgXph1BYseJ+KZd17bKQib/yF3SR+demvytiRXrwd12Blnz5eYGm8tXaeRdd4x88MlfwldHoudGg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/scope-manager": "8.42.0", - "@typescript-eslint/types": "8.42.0", - "@typescript-eslint/typescript-estree": "8.42.0", - "@typescript-eslint/visitor-keys": "8.42.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/project-service": { - "version": "8.42.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.42.0.tgz", - "integrity": "sha512-vfVpLHAhbPjilrabtOSNcUDmBboQNrJUiNAGoImkZKnMjs2TIcWG33s4Ds0wY3/50aZmTMqJa6PiwkwezaAklg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.42.0", - "@typescript-eslint/types": "^8.42.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "8.42.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.42.0.tgz", - "integrity": "sha512-51+x9o78NBAVgQzOPd17DkNTnIzJ8T/O2dmMBLoK9qbY0Gm52XJcdJcCl18ExBMiHo6jPMErUQWUv5RLE51zJw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.42.0", - "@typescript-eslint/visitor-keys": "8.42.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.42.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.42.0.tgz", - "integrity": "sha512-kHeFUOdwAJfUmYKjR3CLgZSglGHjbNTi1H8sTYRYV2xX6eNz4RyJ2LIgsDLKf8Yi0/GL1WZAC/DgZBeBft8QAQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "8.42.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.42.0.tgz", - "integrity": "sha512-9KChw92sbPTYVFw3JLRH1ockhyR3zqqn9lQXol3/YbI6jVxzWoGcT3AsAW0mu1MY0gYtsXnUGV/AKpkAj5tVlQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.42.0", - "@typescript-eslint/typescript-estree": "8.42.0", - "@typescript-eslint/utils": "8.42.0", - "debug": "^4.3.4", - "ts-api-utils": "^2.1.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/types": { - "version": "8.42.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.42.0.tgz", - "integrity": "sha512-LdtAWMiFmbRLNP7JNeY0SqEtJvGMYSzfiWBSmx+VSZ1CH+1zyl8Mmw1TT39OrtsRvIYShjJWzTDMPWZJCpwBlw==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.42.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.42.0.tgz", - "integrity": "sha512-ku/uYtT4QXY8sl9EDJETD27o3Ewdi72hcXg1ah/kkUgBvAYHLwj2ofswFFNXS+FL5G+AGkxBtvGt8pFBHKlHsQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/project-service": "8.42.0", - "@typescript-eslint/tsconfig-utils": "8.42.0", - "@typescript-eslint/types": "8.42.0", - "@typescript-eslint/visitor-keys": "8.42.0", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^2.1.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "8.42.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.42.0.tgz", - "integrity": "sha512-JnIzu7H3RH5BrKC4NoZqRfmjqCIS1u3hGZltDYJgkVdqAezl4L9d1ZLw+36huCujtSBSAirGINF/S4UxOcR+/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.42.0", - "@typescript-eslint/types": "8.42.0", - "@typescript-eslint/typescript-estree": "8.42.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.42.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.42.0.tgz", - "integrity": "sha512-3WbiuzoEowaEn8RSnhJBrxSwX8ULYE9CXaPepS2C2W3NSA5NNIvBaslpBSBElPq0UGr0xVJlXFWOAKIkyylydQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.42.0", - "eslint-visitor-keys": "^4.2.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@ungap/structured-clone": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", - "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", - "license": "ISC" - }, - "node_modules/@vitejs/plugin-react": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.0.2.tgz", - "integrity": "sha512-tmyFgixPZCx2+e6VO9TNITWcCQl8+Nl/E8YbAyPVv85QCc7/A3JrdfG2A8gIzvVhWuzMOVrFW1aReaNxrI6tbw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.28.3", - "@babel/plugin-transform-react-jsx-self": "^7.27.1", - "@babel/plugin-transform-react-jsx-source": "^7.27.1", - "@rolldown/pluginutils": "1.0.0-beta.34", - "@types/babel__core": "^7.20.5", - "react-refresh": "^0.17.0" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "peerDependencies": { - "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" - } - }, - "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/autoprefixer": { - "version": "10.4.21", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz", - "integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/autoprefixer" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "browserslist": "^4.24.4", - "caniuse-lite": "^1.0.30001702", - "fraction.js": "^4.3.7", - "normalize-range": "^0.1.2", - "picocolors": "^1.1.1", - "postcss-value-parser": "^4.2.0" - }, - "bin": { - "autoprefixer": "bin/autoprefixer" - }, - "engines": { - "node": "^10 || ^12 || >=14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/bail": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", - "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.25.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.4.tgz", - "integrity": "sha512-4jYpcjabC606xJ3kw2QwGEZKX0Aw7sgQdZCvIK9dhVSPh76BKo+C+btT1RRofH7B+8iNpEbgGNVWiLki5q93yg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "caniuse-lite": "^1.0.30001737", - "electron-to-chromium": "^1.5.211", - "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.3" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001741", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001741.tgz", - "integrity": "sha512-QGUGitqsc8ARjLdgAfxETDhRbJ0REsP6O3I96TAth/mVjh2cYzN2u+3AzPP3aVSm2FehEItaJw1xd+IGBXWeSw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, - "node_modules/ccount": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", - "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/character-entities": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", - "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-entities-html4": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", - "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-entities-legacy": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", - "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-reference-invalid": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", - "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/chownr": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", - "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/comma-separated-tokens": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", - "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, - "license": "MIT" - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, - "license": "MIT" - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, - "license": "MIT", - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "license": "MIT" - }, - "node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decode-named-character-reference": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.2.0.tgz", - "integrity": "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==", - "license": "MIT", - "dependencies": { - "character-entities": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/detect-libc": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", - "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=8" - } - }, - "node_modules/devlop": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", - "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", - "license": "MIT", - "dependencies": { - "dequal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.5.214", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.214.tgz", - "integrity": "sha512-TpvUNdha+X3ybfU78NoQatKvQEm1oq3lf2QbnmCEdw+Bd9RuIAY+hJTvq1avzHM0f7EJfnH3vbCnbzKzisc/9Q==", - "dev": true, - "license": "ISC" - }, - "node_modules/enhanced-resolve": { - "version": "5.18.3", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz", - "integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/entities": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", - "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/esbuild": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz", - "integrity": "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.9", - "@esbuild/android-arm": "0.25.9", - "@esbuild/android-arm64": "0.25.9", - "@esbuild/android-x64": "0.25.9", - "@esbuild/darwin-arm64": "0.25.9", - "@esbuild/darwin-x64": "0.25.9", - "@esbuild/freebsd-arm64": "0.25.9", - "@esbuild/freebsd-x64": "0.25.9", - "@esbuild/linux-arm": "0.25.9", - "@esbuild/linux-arm64": "0.25.9", - "@esbuild/linux-ia32": "0.25.9", - "@esbuild/linux-loong64": "0.25.9", - "@esbuild/linux-mips64el": "0.25.9", - "@esbuild/linux-ppc64": "0.25.9", - "@esbuild/linux-riscv64": "0.25.9", - "@esbuild/linux-s390x": "0.25.9", - "@esbuild/linux-x64": "0.25.9", - "@esbuild/netbsd-arm64": "0.25.9", - "@esbuild/netbsd-x64": "0.25.9", - "@esbuild/openbsd-arm64": "0.25.9", - "@esbuild/openbsd-x64": "0.25.9", - "@esbuild/openharmony-arm64": "0.25.9", - "@esbuild/sunos-x64": "0.25.9", - "@esbuild/win32-arm64": "0.25.9", - "@esbuild/win32-ia32": "0.25.9", - "@esbuild/win32-x64": "0.25.9" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "9.35.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.35.0.tgz", - "integrity": "sha512-QePbBFMJFjgmlE+cXAlbHZbHpdFVS2E/6vzCy7aKlebddvl1vadiC4JFV5u/wqTkNUwEV8WrQi257jf5f06hrg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.8.0", - "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.21.0", - "@eslint/config-helpers": "^0.3.1", - "@eslint/core": "^0.15.2", - "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.35.0", - "@eslint/plugin-kit": "^0.3.5", - "@humanfs/node": "^0.16.6", - "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.2", - "@types/estree": "^1.0.6", - "@types/json-schema": "^7.0.15", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.6", - "debug": "^4.3.2", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.4.0", - "eslint-visitor-keys": "^4.2.1", - "espree": "^10.4.0", - "esquery": "^1.5.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^8.0.0", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - }, - "peerDependencies": { - "jiti": "*" - }, - "peerDependenciesMeta": { - "jiti": { - "optional": true - } - } - }, - "node_modules/eslint-plugin-react-hooks": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", - "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" - } - }, - "node_modules/eslint-plugin-react-refresh": { - "version": "0.4.20", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.20.tgz", - "integrity": "sha512-XpbHQ2q5gUF8BGOX4dHe+71qoirYMhApEPZ7sfhF/dNnOF1UXnCMGZf79SFTBO7Bz5YEIT4TMieSlJBWhP9WBA==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "eslint": ">=8.40" - } - }, - "node_modules/eslint-scope": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", - "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/espree": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", - "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.15.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estree-util-is-identifier-name": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", - "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "license": "MIT" - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fastq": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", - "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fault": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/fault/-/fault-1.0.4.tgz", - "integrity": "sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA==", - "license": "MIT", - "dependencies": { - "format": "^0.2.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "flat-cache": "^4.0.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", - "dev": true, - "license": "MIT", - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/flatted": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", - "dev": true, - "license": "ISC" - }, - "node_modules/format": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", - "integrity": "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==", - "engines": { - "node": ">=0.4.x" - } - }, - "node_modules/fraction.js": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", - "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - }, - "funding": { - "type": "patreon", - "url": "https://github.com/sponsors/rawify" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/globals": { - "version": "16.3.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-16.3.0.tgz", - "integrity": "sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true, - "license": "MIT" - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/hast-util-from-parse5": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz", - "integrity": "sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "devlop": "^1.0.0", - "hastscript": "^9.0.0", - "property-information": "^7.0.0", - "vfile": "^6.0.0", - "vfile-location": "^5.0.0", - "web-namespaces": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-from-parse5/node_modules/hast-util-parse-selector": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", - "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-from-parse5/node_modules/hastscript": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-9.0.1.tgz", - "integrity": "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "comma-separated-tokens": "^2.0.0", - "hast-util-parse-selector": "^4.0.0", - "property-information": "^7.0.0", - "space-separated-tokens": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-parse-selector": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz", - "integrity": "sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-raw": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.1.0.tgz", - "integrity": "sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "@ungap/structured-clone": "^1.0.0", - "hast-util-from-parse5": "^8.0.0", - "hast-util-to-parse5": "^8.0.0", - "html-void-elements": "^3.0.0", - "mdast-util-to-hast": "^13.0.0", - "parse5": "^7.0.0", - "unist-util-position": "^5.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0", - "web-namespaces": "^2.0.0", - "zwitch": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-to-jsx-runtime": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz", - "integrity": "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "comma-separated-tokens": "^2.0.0", - "devlop": "^1.0.0", - "estree-util-is-identifier-name": "^3.0.0", - "hast-util-whitespace": "^3.0.0", - "mdast-util-mdx-expression": "^2.0.0", - "mdast-util-mdx-jsx": "^3.0.0", - "mdast-util-mdxjs-esm": "^2.0.0", - "property-information": "^7.0.0", - "space-separated-tokens": "^2.0.0", - "style-to-js": "^1.0.0", - "unist-util-position": "^5.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-to-parse5": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.0.tgz", - "integrity": "sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "comma-separated-tokens": "^2.0.0", - "devlop": "^1.0.0", - "property-information": "^6.0.0", - "space-separated-tokens": "^2.0.0", - "web-namespaces": "^2.0.0", - "zwitch": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-to-parse5/node_modules/property-information": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", - "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/hast-util-whitespace": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", - "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hastscript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-6.0.0.tgz", - "integrity": "sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==", - "license": "MIT", - "dependencies": { - "@types/hast": "^2.0.0", - "comma-separated-tokens": "^1.0.0", - "hast-util-parse-selector": "^2.0.0", - "property-information": "^5.0.0", - "space-separated-tokens": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hastscript/node_modules/@types/hast": { - "version": "2.3.10", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.10.tgz", - "integrity": "sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw==", - "license": "MIT", - "dependencies": { - "@types/unist": "^2" - } - }, - "node_modules/hastscript/node_modules/@types/unist": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", - "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", - "license": "MIT" - }, - "node_modules/hastscript/node_modules/comma-separated-tokens": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz", - "integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/hastscript/node_modules/property-information": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz", - "integrity": "sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==", - "license": "MIT", - "dependencies": { - "xtend": "^4.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/hastscript/node_modules/space-separated-tokens": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz", - "integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "license": "MIT", - "bin": { - "he": "bin/he" - } - }, - "node_modules/highlight.js": { - "version": "10.7.3", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", - "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", - "license": "BSD-3-Clause", - "engines": { - "node": "*" - } - }, - "node_modules/highlightjs-vue": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/highlightjs-vue/-/highlightjs-vue-1.0.0.tgz", - "integrity": "sha512-PDEfEF102G23vHmPhLyPboFCD+BkMGu+GuJe2d9/eH4FsCwvgBpnc9n0pGE+ffKdph38s6foEZiEjdgHdzp+IA==", - "license": "CC0-1.0" - }, - "node_modules/html-url-attributes": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz", - "integrity": "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/html-void-elements": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", - "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", - "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inline-style-parser": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.4.tgz", - "integrity": "sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==", - "license": "MIT" - }, - "node_modules/is-alphabetical": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", - "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-alphanumerical": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", - "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", - "license": "MIT", - "dependencies": { - "is-alphabetical": "^2.0.0", - "is-decimal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-decimal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", - "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-hexadecimal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", - "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-plain-obj": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", - "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" - }, - "node_modules/jiti": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.5.1.tgz", - "integrity": "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==", - "dev": true, - "license": "MIT", - "bin": { - "jiti": "lib/jiti-cli.mjs" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lightningcss": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz", - "integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==", - "dev": true, - "license": "MPL-2.0", - "dependencies": { - "detect-libc": "^2.0.3" - }, - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "optionalDependencies": { - "lightningcss-darwin-arm64": "1.30.1", - "lightningcss-darwin-x64": "1.30.1", - "lightningcss-freebsd-x64": "1.30.1", - "lightningcss-linux-arm-gnueabihf": "1.30.1", - "lightningcss-linux-arm64-gnu": "1.30.1", - "lightningcss-linux-arm64-musl": "1.30.1", - "lightningcss-linux-x64-gnu": "1.30.1", - "lightningcss-linux-x64-musl": "1.30.1", - "lightningcss-win32-arm64-msvc": "1.30.1", - "lightningcss-win32-x64-msvc": "1.30.1" - } - }, - "node_modules/lightningcss-darwin-arm64": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.1.tgz", - "integrity": "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-darwin-x64": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.1.tgz", - "integrity": "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-freebsd-x64": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.1.tgz", - "integrity": "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.1.tgz", - "integrity": "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.1.tgz", - "integrity": "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm64-musl": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.1.tgz", - "integrity": "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-x64-gnu": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.1.tgz", - "integrity": "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-x64-musl": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.1.tgz", - "integrity": "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-win32-arm64-msvc": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.1.tgz", - "integrity": "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz", - "integrity": "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash.castarray": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz", - "integrity": "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/longest-streak": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", - "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/lowlight": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/lowlight/-/lowlight-1.20.0.tgz", - "integrity": "sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw==", - "license": "MIT", - "dependencies": { - "fault": "^1.0.0", - "highlight.js": "~10.7.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/magic-string": { - "version": "0.30.18", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.18.tgz", - "integrity": "sha512-yi8swmWbO17qHhwIBNeeZxTceJMeBvWJaId6dyvTSOwTipqeHhMhOrz6513r1sOKnpvQ7zkhlG8tPrpilwTxHQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" - } - }, - "node_modules/mdast-util-from-markdown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", - "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark": "^4.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-decode-string": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unist-util-stringify-position": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdx-expression": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", - "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==", - "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdx-jsx": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz", - "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==", - "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "ccount": "^2.0.0", - "devlop": "^1.1.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0", - "parse-entities": "^4.0.0", - "stringify-entities": "^4.0.0", - "unist-util-stringify-position": "^4.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdxjs-esm": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", - "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", - "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-phrasing": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", - "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-hast": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", - "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "@ungap/structured-clone": "^1.0.0", - "devlop": "^1.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "trim-lines": "^3.0.0", - "unist-util-position": "^5.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-markdown": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", - "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "longest-streak": "^3.0.0", - "mdast-util-phrasing": "^4.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-decode-string": "^2.0.0", - "unist-util-visit": "^5.0.0", - "zwitch": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", - "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromark": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", - "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "@types/debug": "^4.0.0", - "debug": "^4.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-core-commonmark": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", - "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-factory-destination": "^2.0.0", - "micromark-factory-label": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-factory-title": "^2.0.0", - "micromark-factory-whitespace": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-html-tag-name": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-destination": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", - "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-label": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", - "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-space": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", - "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-title": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", - "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-whitespace": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", - "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-character": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", - "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-chunked": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", - "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-classify-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", - "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-combine-extensions": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", - "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-chunked": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-decode-numeric-character-reference": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", - "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-decode-string": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", - "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "decode-named-character-reference": "^1.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-encode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", - "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-html-tag-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", - "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-normalize-identifier": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", - "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-resolve-all": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", - "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-sanitize-uri": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", - "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-subtokenize": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", - "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-symbol": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", - "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-types": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", - "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/minizlib": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz", - "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==", - "dev": true, - "license": "MIT", - "dependencies": { - "minipass": "^7.1.2" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/mkdirp": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", - "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", - "dev": true, - "license": "MIT", - "bin": { - "mkdirp": "dist/cjs/src/bin.js" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, - "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true, - "license": "MIT" - }, - "node_modules/node-releases": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.20.tgz", - "integrity": "sha512-7gK6zSXEH6neM212JgfYFXe+GmZQM+fia5SsusuBIUgnPheLFBmIPhtFoAQRj8/7wASYQnbDlHPVwY0BefoFgA==", - "dev": true, - "license": "MIT" - }, - "node_modules/normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dev": true, - "license": "MIT", - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "license": "MIT", - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-entities": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", - "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", - "license": "MIT", - "dependencies": { - "@types/unist": "^2.0.0", - "character-entities-legacy": "^3.0.0", - "character-reference-invalid": "^2.0.0", - "decode-named-character-reference": "^1.0.0", - "is-alphanumerical": "^2.0.0", - "is-decimal": "^2.0.0", - "is-hexadecimal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/parse-entities/node_modules/@types/unist": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", - "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", - "license": "MIT" - }, - "node_modules/parse5": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", - "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", - "license": "MIT", - "dependencies": { - "entities": "^6.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", - "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", - "dev": true, - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prismjs": { - "version": "1.30.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz", - "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/property-information": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", - "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/react": { - "version": "19.1.1", - "resolved": "https://registry.npmjs.org/react/-/react-19.1.1.tgz", - "integrity": "sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "19.1.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.1.tgz", - "integrity": "sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw==", - "license": "MIT", - "dependencies": { - "scheduler": "^0.26.0" - }, - "peerDependencies": { - "react": "^19.1.1" - } - }, - "node_modules/react-markdown": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-10.1.0.tgz", - "integrity": "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "hast-util-to-jsx-runtime": "^2.0.0", - "html-url-attributes": "^3.0.0", - "mdast-util-to-hast": "^13.0.0", - "remark-parse": "^11.0.0", - "remark-rehype": "^11.0.0", - "unified": "^11.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - }, - "peerDependencies": { - "@types/react": ">=18", - "react": ">=18" - } - }, - "node_modules/react-refresh": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", - "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-syntax-highlighter": { - "version": "15.6.6", - "resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-15.6.6.tgz", - "integrity": "sha512-DgXrc+AZF47+HvAPEmn7Ua/1p10jNoVZVI/LoPiYdtY+OM+/nG5yefLHKJwdKqY1adMuHFbeyBaG9j64ML7vTw==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.3.1", - "highlight.js": "^10.4.1", - "highlightjs-vue": "^1.0.0", - "lowlight": "^1.17.0", - "prismjs": "^1.30.0", - "refractor": "^3.6.0" - }, - "peerDependencies": { - "react": ">= 0.14.0" - } - }, - "node_modules/refractor": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/refractor/-/refractor-3.6.0.tgz", - "integrity": "sha512-MY9W41IOWxxk31o+YvFCNyNzdkc9M20NoZK5vq6jkv4I/uh2zkWcfudj0Q1fovjUQJrNewS9NMzeTtqPf+n5EA==", - "license": "MIT", - "dependencies": { - "hastscript": "^6.0.0", - "parse-entities": "^2.0.0", - "prismjs": "~1.27.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/refractor/node_modules/character-entities": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", - "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/refractor/node_modules/character-entities-legacy": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", - "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/refractor/node_modules/character-reference-invalid": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", - "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/refractor/node_modules/is-alphabetical": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", - "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/refractor/node_modules/is-alphanumerical": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", - "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", - "license": "MIT", - "dependencies": { - "is-alphabetical": "^1.0.0", - "is-decimal": "^1.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/refractor/node_modules/is-decimal": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz", - "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/refractor/node_modules/is-hexadecimal": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", - "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/refractor/node_modules/parse-entities": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz", - "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==", - "license": "MIT", - "dependencies": { - "character-entities": "^1.0.0", - "character-entities-legacy": "^1.0.0", - "character-reference-invalid": "^1.0.0", - "is-alphanumerical": "^1.0.0", - "is-decimal": "^1.0.0", - "is-hexadecimal": "^1.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/refractor/node_modules/prismjs": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.27.0.tgz", - "integrity": "sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/rehype-raw": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz", - "integrity": "sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "hast-util-raw": "^9.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-parse": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", - "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-from-markdown": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-rehype": { - "version": "11.1.2", - "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz", - "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "mdast-util-to-hast": "^13.0.0", - "unified": "^11.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/reusify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rollup": { - "version": "4.50.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.50.1.tgz", - "integrity": "sha512-78E9voJHwnXQMiQdiqswVLZwJIzdBKJ1GdI5Zx6XwoFKUIk09/sSrr+05QFzvYb8q6Y9pPV45zzDuYa3907TZA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.8" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.50.1", - "@rollup/rollup-android-arm64": "4.50.1", - "@rollup/rollup-darwin-arm64": "4.50.1", - "@rollup/rollup-darwin-x64": "4.50.1", - "@rollup/rollup-freebsd-arm64": "4.50.1", - "@rollup/rollup-freebsd-x64": "4.50.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.50.1", - "@rollup/rollup-linux-arm-musleabihf": "4.50.1", - "@rollup/rollup-linux-arm64-gnu": "4.50.1", - "@rollup/rollup-linux-arm64-musl": "4.50.1", - "@rollup/rollup-linux-loongarch64-gnu": "4.50.1", - "@rollup/rollup-linux-ppc64-gnu": "4.50.1", - "@rollup/rollup-linux-riscv64-gnu": "4.50.1", - "@rollup/rollup-linux-riscv64-musl": "4.50.1", - "@rollup/rollup-linux-s390x-gnu": "4.50.1", - "@rollup/rollup-linux-x64-gnu": "4.50.1", - "@rollup/rollup-linux-x64-musl": "4.50.1", - "@rollup/rollup-openharmony-arm64": "4.50.1", - "@rollup/rollup-win32-arm64-msvc": "4.50.1", - "@rollup/rollup-win32-ia32-msvc": "4.50.1", - "@rollup/rollup-win32-x64-msvc": "4.50.1", - "fsevents": "~2.3.2" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/scheduler": { - "version": "0.26.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", - "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", - "license": "MIT" - }, - "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/space-separated-tokens": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", - "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/stringify-entities": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", - "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", - "license": "MIT", - "dependencies": { - "character-entities-html4": "^2.0.0", - "character-entities-legacy": "^3.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/style-to-js": { - "version": "1.1.17", - "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.17.tgz", - "integrity": "sha512-xQcBGDxJb6jjFCTzvQtfiPn6YvvP2O8U1MDIPNfJQlWMYfktPy+iGsHE7cssjs7y84d9fQaK4UF3RIJaAHSoYA==", - "license": "MIT", - "dependencies": { - "style-to-object": "1.0.9" - } - }, - "node_modules/style-to-object": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.9.tgz", - "integrity": "sha512-G4qppLgKu/k6FwRpHiGiKPaPTFcG3g4wNVX/Qsfu+RqQM30E7Tyu/TEgxcL9PNLF5pdRLwQdE3YKKf+KF2Dzlw==", - "license": "MIT", - "dependencies": { - "inline-style-parser": "0.2.4" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/tailwindcss": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.13.tgz", - "integrity": "sha512-i+zidfmTqtwquj4hMEwdjshYYgMbOrPzb9a0M3ZgNa0JMoZeFC6bxZvO8yr8ozS6ix2SDz0+mvryPeBs2TFE+w==", - "dev": true, - "license": "MIT" - }, - "node_modules/tapable": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.3.tgz", - "integrity": "sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/tar": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", - "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", - "dev": true, - "license": "ISC", - "dependencies": { - "@isaacs/fs-minipass": "^4.0.0", - "chownr": "^3.0.0", - "minipass": "^7.1.2", - "minizlib": "^3.0.1", - "mkdirp": "^3.0.1", - "yallist": "^5.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/tar/node_modules/yallist": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", - "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } - }, - "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.3" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/trim-lines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", - "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/trough": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", - "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/ts-api-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", - "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18.12" - }, - "peerDependencies": { - "typescript": ">=4.8.4" - } - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/typescript": { - "version": "5.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", - "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/typescript-eslint": { - "version": "8.42.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.42.0.tgz", - "integrity": "sha512-ozR/rQn+aQXQxh1YgbCzQWDFrsi9mcg+1PM3l/z5o1+20P7suOIaNg515bpr/OYt6FObz/NHcBstydDLHWeEKg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/eslint-plugin": "8.42.0", - "@typescript-eslint/parser": "8.42.0", - "@typescript-eslint/typescript-estree": "8.42.0", - "@typescript-eslint/utils": "8.42.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/unified": { - "version": "11.0.5", - "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", - "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "bail": "^2.0.0", - "devlop": "^1.0.0", - "extend": "^3.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-is": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-position": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", - "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-stringify-position": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", - "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", - "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit-parents": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", - "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", - "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true, - "license": "MIT" - }, - "node_modules/vfile": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", - "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vfile-location": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz", - "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vfile-message": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", - "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vite": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.5.tgz", - "integrity": "sha512-4cKBO9wR75r0BeIWWWId9XK9Lj6La5X846Zw9dFfzMRw38IlTk2iCcUt6hsyiDRcPidc55ZParFYDXi0nXOeLQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.25.0", - "fdir": "^6.5.0", - "picomatch": "^4.0.3", - "postcss": "^8.5.6", - "rollup": "^4.43.0", - "tinyglobby": "^0.2.15" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^20.19.0 || >=22.12.0", - "jiti": ">=1.21.0", - "less": "^4.0.0", - "lightningcss": "^1.21.0", - "sass": "^1.70.0", - "sass-embedded": "^1.70.0", - "stylus": ">=0.54.8", - "sugarss": "^5.0.0", - "terser": "^5.16.0", - "tsx": "^4.8.1", - "yaml": "^2.4.2" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "jiti": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - }, - "tsx": { - "optional": true - }, - "yaml": { - "optional": true - } - } - }, - "node_modules/vite/node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/vite/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/web-namespaces": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", - "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "license": "MIT", - "engines": { - "node": ">=0.4" - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true, - "license": "ISC" - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/zwitch": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", - "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - } - } -} diff --git a/pmoapp/web/package.json b/pmoapp/web/package.json deleted file mode 100644 index aac8be96..00000000 --- a/pmoapp/web/package.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "name": "web", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build": "tsc -b && vite build", - "lint": "eslint .", - "preview": "vite preview" - }, - "dependencies": { - "@types/react-syntax-highlighter": "^15.5.13", - "he": "^1.2.0", - "react": "^19.1.1", - "react-dom": "^19.1.1", - "react-markdown": "^10.1.0", - "react-syntax-highlighter": "^15.6.6", - "rehype-raw": "^7.0.0" - }, - "devDependencies": { - "@eslint/js": "^9.33.0", - "@tailwindcss/postcss": "^4.1.13", - "@tailwindcss/typography": "^0.5.16", - "@types/he": "^1.2.3", - "@types/react": "^19.1.10", - "@types/react-dom": "^19.1.7", - "@vitejs/plugin-react": "^5.0.0", - "autoprefixer": "^10.4.21", - "eslint": "^9.33.0", - "eslint-plugin-react-hooks": "^5.2.0", - "eslint-plugin-react-refresh": "^0.4.20", - "globals": "^16.3.0", - "postcss": "^8.5.6", - "tailwindcss": "^4.1.13", - "typescript": "~5.8.3", - "typescript-eslint": "^8.39.1", - "vite": "^7.1.2" - } -} diff --git a/pmoapp/web/postcss.config.mjs b/pmoapp/web/postcss.config.mjs deleted file mode 100644 index b87c4dea..00000000 --- a/pmoapp/web/postcss.config.mjs +++ /dev/null @@ -1,6 +0,0 @@ -export default { - plugins: { - "@tailwindcss/postcss": {}, - // autoprefixer est inclus par défaut dans v4, donc souvent optionnel - }, -} \ No newline at end of file diff --git a/pmoapp/web/public/vite.svg b/pmoapp/web/public/vite.svg deleted file mode 100644 index e7b8dfb1..00000000 --- a/pmoapp/web/public/vite.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/pmoapp/web/src/App.css b/pmoapp/web/src/App.css deleted file mode 100644 index 2b1071b2..00000000 --- a/pmoapp/web/src/App.css +++ /dev/null @@ -1,207 +0,0 @@ -/* App.css ou index.css */ -@import "tailwindcss"; - -/* Styles de base améliorés */ -:root { - font-family: 'SF Pro Display', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif; - line-height: 1.6; - font-weight: 400; - color-scheme: light dark; - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -/* Styles pour le conteneur principal */ -.log-container { - @apply p-4 space-y-3 min-h-screen; - max-width: 100%; - overflow-x: hidden; -} - -/* Styles généraux pour les entrées de log améliorées */ -.log-entry { - @apply rounded-xl p-4 font-mono shadow-lg transition-all duration-300 ease-out; - border-left: 4px solid; - backdrop-filter: blur(10px); - transform-origin: center top; -} - -/* Animation d'entrée pour les nouveaux logs */ -@keyframes slideIn { - 0% { - opacity: 0; - transform: translateY(-10px); - } - 100% { - opacity: 1; - transform: translateY(0); - } -} - -.log-entry:first-child { - animation: slideIn 0.4s ease-out; -} - -/* Styles pour le thème sombre - améliorés */ -.dark .log-entry { - background: linear-gradient(90deg, rgba(30, 30, 30, 0.7), rgba(30, 30, 30, 0.4)); - border-top: 1px solid rgba(255, 255, 255, 0.05); -} - -.dark .log-entry.info { - border-color: #3b82f6; - box-shadow: 0 4px 12px rgba(59, 130, 246, 0.15); -} - -.dark .log-entry.warning { - border-color: #f59e0b; - box-shadow: 0 4px 12px rgba(245, 158, 11, 0.15); -} - -.dark .log-entry.error { - border-color: #ef4444; - box-shadow: 0 4px 12px rgba(239, 68, 68, 0.15); -} - -.dark .log-entry.debug { - border-color: #8b5cf6; - box-shadow: 0 4px 12px rgba(139, 92, 246, 0.15); -} - -.dark .log-entry:hover { - transform: translateY(-2px); - box-shadow: 0 6px 16px rgba(0, 0, 0, 0.3); -} - -/* Styles pour les éléments de détail et code */ -.dark details { - @apply mt-3 rounded-lg overflow-hidden; - background: rgba(20, 20, 20, 0.6); -} - -.dark summary { - @apply p-2 cursor-pointer font-semibold flex items-center; - background: rgba(0, 0, 0, 0.2); - user-select: none; -} - -.dark summary::before { - content: "►"; - @apply mr-2 text-xs transition-transform; -} - -.dark details[open] summary::before { - transform: rotate(90deg); -} - -.dark pre { - @apply p-4 overflow-x-auto; - background: rgba(10, 10, 10, 0.8) !important; - border-left: 3px solid rgba(255, 255, 255, 0.1); -} - -.dark code { - @apply text-sm; - font-family: 'Fira Code', 'Monaco', 'Cascadia Code', monospace; -} - -/* Styles pour les éléments spécifiques dans les logs */ -.dark .bg-black { - background: rgba(0, 0, 0, 0.3) !important; -} - -.dark ul { - @apply mt-2 space-y-1; -} - -.dark li { - @apply flex; -} - -.dark li strong { - @apply min-w-[100px] text-neutral-300; -} - -.dark img { - @apply rounded-lg mt-2 max-h-24 border border-neutral-700; -} - -/* Amélioration du header */ -.dark header { - @apply sticky top-0 z-10 shadow-md border-b border-neutral-700; - background: rgba(23, 23, 23, 0.95); - backdrop-filter: blur(10px); -} - -.dark button { - @apply transition-all duration-200; -} - -.dark button:hover { - transform: translateY(-1px); - box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3); -} - -/* Barre de défilement personnalisée */ -.dark ::-webkit-scrollbar { - width: 10px; -} - -.dark ::-webkit-scrollbar-track { - background: rgba(30, 30, 30, 0.5); - border-radius: 5px; -} - -.dark ::-webkit-scrollbar-thumb { - background: rgba(90, 90, 90, 0.5); - border-radius: 5px; -} - -.dark ::-webkit-scrollbar-thumb:hover { - background: rgba(120, 120, 120, 0.6); -} - -/* Styles pour les messages spécifiques */ -.log-entry .emoji { - @apply mr-2; -} - -.log-entry .ip-address { - @apply font-bold text-amber-400; -} - -.log-entry .success { - @apply text-green-400; -} - -/* Responsive design */ -@media (max-width: 768px) { - .log-entry { - @apply p-3; - } - - .dark header { - @apply flex-col space-y-2 items-start; - } - - .dark header h1 { - @apply text-lg; - } - - .dark pre { - @apply text-xs; - } -} - -/* Animation de pulse pour les logs actifs */ -@keyframes pulseSubtle { - 0% { opacity: 0.9; } - 50% { opacity: 1; } - 100% { opacity: 0.9; } -} - -.log-entry:first-child { - animation: slideIn 0.4s ease-out, pulseSubtle 3s infinite; -} \ No newline at end of file diff --git a/pmoapp/web/src/App.tsx b/pmoapp/web/src/App.tsx deleted file mode 100644 index 3cdafcfd..00000000 --- a/pmoapp/web/src/App.tsx +++ /dev/null @@ -1,73 +0,0 @@ -// App.tsx -import { useEffect, useState } from "react"; -import { Logs, type LogEntry } from "./Logs"; -import { Covers } from "./Covers"; -import "./App.css"; - -export default function App() { - const [theme, setTheme] = useState<"light" | "dark">("dark"); - const [logs, setLogs] = useState([]); - const [view, setView] = useState<"logs" | "covers">("logs"); - - const toggleTheme = () => - setTheme((prev) => (prev === "dark" ? "light" : "dark")); - - const mapSSEToLogEntry = (sseData: any, index: number): LogEntry => ({ - id: sseData.time || `log-${index}`, - level: sseData.level || "info", - message: sseData.content || "", - }); - - useEffect(() => { - const evtSource = new EventSource("/log-sse"); - let idx = 0; - - evtSource.addEventListener("message", (e: MessageEvent) => { - try { - const data = JSON.parse(e.data); - const newLog = mapSSEToLogEntry(data, idx++); - setLogs((prev) => [...prev, newLog]); - } catch (err) { - console.error("Erreur parsing SSE:", err); - } - }); - - return () => { - evtSource.close(); - }; - }, []); - - return ( -
-
-

PMO-Music

-
- - - -
-
- {view === "logs" && } - {view === "covers" && } -
- ); -} diff --git a/pmoapp/web/src/Covers.tsx b/pmoapp/web/src/Covers.tsx deleted file mode 100644 index 25f78202..00000000 --- a/pmoapp/web/src/Covers.tsx +++ /dev/null @@ -1,46 +0,0 @@ -// Covers.tsx -import { useEffect, useState } from "react"; - -type CoverEntry = { - pk: string; - source_url: string; - hits: number; -}; - -export function Covers() { - const [covers, setCovers] = useState([]); - - useEffect(() => { - fetch("/covers/stats") - .then((res) => res.json()) - .then((data) => { - setCovers(data.top_hits || []); - }) - .catch((err) => console.error("Erreur stats covers:", err)); - }, []); - - return ( -
-

- Top Covers -

-
- {covers.map((cover) => ( -
- {cover.source_url} -

- {cover.hits} hits -

-
- ))} -
-
- ); -} diff --git a/pmoapp/web/src/Logs.tsx b/pmoapp/web/src/Logs.tsx deleted file mode 100644 index 586df015..00000000 --- a/pmoapp/web/src/Logs.tsx +++ /dev/null @@ -1,65 +0,0 @@ -// Logs.tsx -import ReactMarkdown from "react-markdown"; -import rehypeRaw from "rehype-raw"; - -export type LogEntry = { - id: string; - level: "info" | "warn" | "error" | "debug"; - message: string; -}; - -type LogsProps = { - logs: LogEntry[]; - theme: "light" | "dark"; -}; - -export function Logs({ logs }: LogsProps) { - const levelClass = (level: LogEntry["level"]) => { - switch (level) { - case "info": - return "bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200"; - case "warn": - return "bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200"; - case "error": - return "bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200"; - case "debug": - return "bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-200"; - default: - return "bg-gray-100 dark:bg-gray-800"; - } - }; - - const decodeMessage = (msg: string) => { - const txt = document.createElement("textarea"); - txt.innerHTML = msg; - return txt.value; - }; - - return ( -
- {logs.map((log) => ( -
- - {children} - - ); - }, - }} - /> -
- ))} -
- ); -} diff --git a/pmoapp/web/src/assets/react.svg b/pmoapp/web/src/assets/react.svg deleted file mode 100644 index 6c87de9b..00000000 --- a/pmoapp/web/src/assets/react.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/pmoapp/web/src/custom.d.ts b/pmoapp/web/src/custom.d.ts deleted file mode 100644 index 341cee2f..00000000 --- a/pmoapp/web/src/custom.d.ts +++ /dev/null @@ -1,20 +0,0 @@ -// Déclare les modules CSS pour que TypeScript les accepte -declare module '*.css' - -// Déclare les fichiers SVG pour que TypeScript les accepte -declare module '*.svg' { - const content: string - export default content -} - -// Déclare les fichiers PNG, JPG si tu en utilises -declare module '*.png' -declare module '*.jpg' -declare module '*.jpeg' -declare module '*.gif' - -// Déclare les fichiers JSON si nécessaire -declare module '*.json' { - const value: any - export default value -} diff --git a/pmoapp/web/src/index.css b/pmoapp/web/src/index.css deleted file mode 100644 index 51178550..00000000 --- a/pmoapp/web/src/index.css +++ /dev/null @@ -1,68 +0,0 @@ -:root { - font-family: system-ui, Avenir, Helvetica, Arial, sans-serif; - line-height: 1.5; - font-weight: 400; - - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: #242424; - - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} -a:hover { - color: #535bf2; -} - -body { - margin: 0; - display: flex; - place-items: center; - min-width: 320px; - min-height: 100vh; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -button { - border-radius: 8px; - border: 1px solid transparent; - padding: 0.6em 1.2em; - font-size: 1em; - font-weight: 500; - font-family: inherit; - background-color: #1a1a1a; - cursor: pointer; - transition: border-color 0.25s; -} -button:hover { - border-color: #646cff; -} -button:focus, -button:focus-visible { - outline: 4px auto -webkit-focus-ring-color; -} - -/* @media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - a:hover { - color: #747bff; - } - button { - background-color: #f9f9f9; - } -} */ diff --git a/pmoapp/web/src/main.tsx b/pmoapp/web/src/main.tsx deleted file mode 100644 index 9be2d891..00000000 --- a/pmoapp/web/src/main.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import React from "react"; -import ReactDOM from "react-dom/client"; -import App from "./App"; -import "./index.css"; - -ReactDOM.createRoot(document.getElementById("root")!).render( - - - -); \ No newline at end of file diff --git a/pmoapp/web/src/vite-env.d.ts b/pmoapp/web/src/vite-env.d.ts deleted file mode 100644 index 11f02fe2..00000000 --- a/pmoapp/web/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/pmoapp/web/tailwind.config.js b/pmoapp/web/tailwind.config.js deleted file mode 100644 index d9989db0..00000000 --- a/pmoapp/web/tailwind.config.js +++ /dev/null @@ -1,5 +0,0 @@ -module.exports = { - content: ["./src/**/*.{js,ts,jsx,tsx}"], - theme: { extend: {} }, - plugins: [require("@tailwindcss/typography")], -}; diff --git a/pmoapp/web/tsconfig.app.json b/pmoapp/web/tsconfig.app.json deleted file mode 100644 index 227a6c67..00000000 --- a/pmoapp/web/tsconfig.app.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "compilerOptions": { - "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", - "target": "ES2022", - "useDefineForClassFields": true, - "lib": ["ES2022", "DOM", "DOM.Iterable"], - "module": "ESNext", - "skipLibCheck": true, - - /* Bundler mode */ - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "verbatimModuleSyntax": true, - "moduleDetection": "force", - "noEmit": true, - "jsx": "react-jsx", - - /* Linting */ - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "erasableSyntaxOnly": true, - "noFallthroughCasesInSwitch": true, - "noUncheckedSideEffectImports": true - }, - "include": ["src"] -} diff --git a/pmoapp/web/tsconfig.json b/pmoapp/web/tsconfig.json deleted file mode 100644 index 1ffef600..00000000 --- a/pmoapp/web/tsconfig.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "files": [], - "references": [ - { "path": "./tsconfig.app.json" }, - { "path": "./tsconfig.node.json" } - ] -} diff --git a/pmoapp/web/tsconfig.node.json b/pmoapp/web/tsconfig.node.json deleted file mode 100644 index f85a3990..00000000 --- a/pmoapp/web/tsconfig.node.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "compilerOptions": { - "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", - "target": "ES2023", - "lib": ["ES2023"], - "module": "ESNext", - "skipLibCheck": true, - - /* Bundler mode */ - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "verbatimModuleSyntax": true, - "moduleDetection": "force", - "noEmit": true, - - /* Linting */ - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "erasableSyntaxOnly": true, - "noFallthroughCasesInSwitch": true, - "noUncheckedSideEffectImports": true - }, - "include": ["vite.config.ts"] -} diff --git a/pmoapp/web/vite.config.ts b/pmoapp/web/vite.config.ts deleted file mode 100644 index 25fdd2a2..00000000 --- a/pmoapp/web/vite.config.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { defineConfig } from "vite"; -import react from "@vitejs/plugin-react"; - -export default defineConfig({ - base: "/log/", - plugins: [react()], -}); diff --git a/pmoconfig/config.go b/pmoconfig/config.go deleted file mode 100644 index fe1df3c8..00000000 --- a/pmoconfig/config.go +++ /dev/null @@ -1,410 +0,0 @@ -package pmoconfig - -import ( - _ "embed" - "fmt" - "os" - "os/user" - "path" - "strconv" - "strings" - "sync" - - "gargoton.petite-maison-orange.fr/eric/pmomusic/fileutils" - "github.com/google/uuid" - log "github.com/sirupsen/logrus" - "gopkg.in/yaml.v3" -) - -//go:embed pmomusic.yaml -var defaultConfig []byte - -type Config struct { - path string - mutex sync.Mutex - config map[string]interface{} -} - -var _CONFIG *Config - -const envConfigFile = "PMOMUSIC_CONFIG" -const envPrefix = "PMOMUSIC_CONFIG__" - -// LoadConfig loads a configuration file from the given path or a default -// location. -// -// It prioritizes paths in this order: -// - the provided path, -// - the file specified by the environment variable PMOMUSIC_CONFIG -// - the .pmomusic.yml file in the current directory -// - the .pmomusic.yml file in the user's home directory, and . If no path is found -// -// or it fails to read any of these files, it falls back on a default -// configuration. -// -// Parameters: -// - path string: The path to the configuration file. If this -// parameter is empty, the function will look for the configuration in the -// current user's home directory and an environment variable. -// -// Returns: 1) Config: A struct containing the loaded configuration data. -// -// Side Effects: -// -// - This function reads from disk, logs informational messages, and may also -// panic if there are issues unmarshalling the YAML config file. -// -// Errors: -// -// - The function will log a warning message and continue with a default -// configuration if it fails to read or unmarshal any of the files. It does not -// return an error in this case, as returning errors from within deferred -// functions can cause unexpected behavior. -// -// - If there's an issue reading or unmarshalling the YAML file, the function -// will panic as this is a fatal condition that should be addressed immediately. -// -// Edge Cases: -// -// - This function does not handle race conditions where the -// configuration file could change between when it checks if the path is empty -// and when it attempts to read from it. If the file changes in that time, an -// error will occur. -// -// - This function assumes the YAML config files are formatted correctly. If -// they're not, unmarshalling them into a struct may result in unexpected -// behavior or errors. -// -// Usage: ``` go cfg := LoadConfig("/path/to/config") fmt.Println(cfg) ```` -func LoadConfig(filename string) *Config { - var data []byte - var err error - var cfg = &Config{} - - cfg.mutex.Lock() - defer cfg.mutex.Unlock() - - path := filename - - if path != "" { - log.Infof("✅ Trying to load config %s", path) - data, err = os.ReadFile(path) - if err != nil { - log.Warnf("❌ cannot read config file %s", path) - path = "" - } - } - - if path == "" { - path = os.Getenv(envConfigFile) - if path != "" { - log.Infof("✅ Trying to load config specified in env var %s", envConfigFile) - data, err = os.ReadFile(path) - if err != nil { - log.Warnf("❌ cannot read config file %s specified in env var %s", path, envConfigFile) - path = "" - } - } - } - - if path == "" { - path = ".pmomusic.yml" - dir, err := os.Getwd() - if err != nil { - dir = "." - } - log.Infof("✅ Trying to load config file %s/.pmomusic.yml", dir) - data, err = os.ReadFile(path) - if err != nil { - log.Warnf("❌ I cannot read config file %s/.pmomusic.yml", dir) - path = "" - } - } - - if path == "" { - path = getHomeYmlPath() - log.Infof("✅ Trying to load config file from user's home %s", path) - data, err = os.ReadFile(path) - if err != nil { - log.Warnf("❌ I cannot read config file %s", path) - path = "" - } - } - - if path == "" { - log.Infof("✅ Using default embeded config") - data = defaultConfig - } - - if err := yaml.Unmarshal(data, &cfg.config); err != nil { - log.Panicf("invalid YAML config: %v", err) - } - - cfg.config = lowerKeysMap(cfg.config) - - applyEnvOverrides(cfg) - - if path == "" { - switch { - case filename != "" && fileutils.IsWriteable(filename): - path = filename - case os.Getenv(envConfigFile) != "" && fileutils.IsWriteable(os.Getenv(envConfigFile)): - path = os.Getenv(envConfigFile) - case fileutils.IsWriteable(".pmomusic.yml"): - path = ".pmomusic.yml" - case fileutils.IsWriteable(getHomeYmlPath()): - path = getHomeYmlPath() - } - } else { - if !fileutils.IsWriteable(path) { - path = "" - } - } - - if path == "" { - log.Panic("I cannot find a place to store config file") - } - - log.Infof("✅ Config file will be stored in %s", path) - - cfg.path = path - cfg.mutex.Unlock() - cfg.Save() - cfg.mutex.Lock() - return cfg - -} - -func (cfg *Config) Save() error { - cfg.mutex.Lock() - defer cfg.mutex.Unlock() - - cfg.config = lowerKeysMap(cfg.config) - - data, err := yaml.Marshal(cfg.config) - if err != nil { - return err - } - - return os.WriteFile(cfg.path, data, 0644) -} - -func (cfg *Config) SetValue(path []string, value interface{}) { - cfg.setValue(path, value) - cfg.Save() -} - -func (cfg *Config) GetValue(path []string) (interface{}, error) { - cfg.mutex.Lock() - defer cfg.mutex.Unlock() - - current := cfg.config - for i, key := range path { - key = strings.ToLower(key) - - next, ok := current[key] - if !ok { - return nil, fmt.Errorf("path %s does not exist", strings.Join(path[:i+1], ".")) - } - if i < len(path)-1 { - current, ok = next.(map[string]interface{}) - if !ok { - return nil, fmt.Errorf("path %s is not a Config", strings.Join(path[:i+1], ".")) - } - continue - } - return next, nil - } - return nil, fmt.Errorf("path %s does not exist", strings.Join(path[:], ".")) -} - -// overrideConfig sets a value in a nested map[string]interface{} at the given path. -func (cfg *Config) setValue(path []string, value interface{}) { - cfg.mutex.Lock() - defer cfg.mutex.Unlock() - - current := cfg.config - for i, key := range path { - key = strings.ToLower(key) - if i == len(path)-1 { - current[key] = value - return - } - // ensure intermediate maps exist - if _, ok := current[key]; !ok { - current[key] = make(map[string]interface{}) - } - next, ok := current[key].(map[string]interface{}) - if !ok { - // If the path conflicts with a non-object, overwrite it - next = make(map[string]interface{}) - current[key] = next - } - current = next - } -} - -// getHomeYmlPath constructs and returns the path to the home directory of the -// current user followed by ".pmomusic.yml". -// -// This function does not take any parameters but it relies on the -// `user.Current()` function, which can return an error if it fails to determine -// the current user or their home directory. In such cases, a description of the -// error is printed to standard output and the empty string is returned. -// -// The function returns a string representing the path to the file in the -// following format: "$HOME/.pmomusic.yml". It does not return an error value -// since no errors are expected to occur during normal operation. -// -// Side Effects: None. This is a pure function that only depends on input and -// produces output without changing any state or causing side effects, except -// for the printing of potential error messages. -// -// Edge Cases: If `user.Current()` fails to determine the current user's home -// directory or the current user, an empty string is returned and a description -// of the error is printed. -// -// Example usage: -// -// fmt.Println(getHomeYmlPath()) -// -// This will print something like "/Users/username/.pmomusic.yml" on macOS or Linux, or "C:\Users\Username\" on Windows if the current user's home directory is "C:\Users\Username". -func getHomeYmlPath() string { - usr, err := user.Current() - if err != nil { - fmt.Println(err) - } - return path.Join(usr.HomeDir, ".pmomusic.yml") -} - -func applyEnvOverrides(cfg *Config) { - for _, env := range os.Environ() { - if !strings.HasPrefix(env, envPrefix) { - continue - } - - // Split env var into key and value - parts := strings.SplitN(env, "=", 2) - if len(parts) != 2 { - continue - } - - keyPath := strings.Split(strings.TrimPrefix(parts[0], envPrefix), "__") - value := parts[1] - - overrideConfig(cfg, keyPath, value) - } -} - -func convertYAMLScalar(s string) interface{} { - var out interface{} - err := yaml.Unmarshal([]byte(s), &out) - if err != nil { - // fallback: keep string if parsing failed - return s - } - return out -} - -func overrideConfig(cfg *Config, keyPath []string, value string) { - iv := convertYAMLScalar(value) - cfg.setValue(keyPath, iv) -} - -func lowerKeysMap(m map[string]interface{}) map[string]interface{} { - out := make(map[string]interface{}) - for k, v := range m { - lk := strings.ToLower(k) - // si c'est une map imbriquée, traiter récursivement - switch vv := v.(type) { - case map[string]interface{}: - out[lk] = lowerKeysMap(vv) - default: - out[lk] = v - } - } - return out -} - -func GetConfig() *Config { - - if _CONFIG == nil { - _CONFIG = LoadConfig("") - } - - return _CONFIG -} - -func (conf *Config) GetBaseURL() string { - url, _ := conf.GetValue([]string{"host", "base_url"}) - surl, ok := url.(string) - if !ok { - return "" - } - return surl -} - -func (conf *Config) GetHTTPPort() int { - port, _ := conf.GetValue([]string{"host", "http_port"}) - - switch val := port.(type) { - case int: - return val - case int64: - return int(val) - case float64: - return int(val) - case string: - i, err := strconv.Atoi(val) - if err == nil { - return i - } - default: - return 1900 - } - - return 1900 -} - -func (conf *Config) GetDeviceUDN(devtype, name string) string { - udn, error := conf.GetValue([]string{"devices", string(devtype), name, "udn"}) - - if error != nil { - udn = uuid.New().String() - conf.SetValue([]string{"devices", string(devtype), name, "udn"}, udn) - conf.Save() - } - - return udn.(string) -} - -func (conf *Config) GetCoverCacheDir() string { - cachedir, _ := conf.GetValue([]string{"host", "cover_cache", "directory"}) - if cachedir == nil { - cachedir = "./.pmomusic_covers" - } - - sdir, ok := cachedir.(string) - - if ok && sdir != "" { - return sdir - } - - return "./.pmomusic_covers" -} - -func (conf *Config) GetCoverCacheSize() int { - size, _ := conf.GetValue([]string{"host", "cover_cache", "size"}) - if size == nil { - return 2000 - } - - switch v := size.(type) { - case float64: - return int(v) - case int: - return v - default: - return 2000 - } -} diff --git a/pmoconfig/pmomusic.yaml b/pmoconfig/pmomusic.yaml deleted file mode 100644 index c2acfad7..00000000 --- a/pmoconfig/pmomusic.yaml +++ /dev/null @@ -1,11 +0,0 @@ -host: - http_port: "8080" - cover_cache: - directory: "./.pmomusic_covers" - size: 2000 -devices: - mediarenderer: - mpd_renderer: - mediaserver: - qobuz: - udn: "uuid:28963b75-4c5f-4da7-b10e-ffafd" \ No newline at end of file diff --git a/pmocover/cache.go b/pmocover/cache.go deleted file mode 100644 index 2dea9cba..00000000 --- a/pmocover/cache.go +++ /dev/null @@ -1,209 +0,0 @@ -package pmocover - -import ( - "bytes" - "crypto/sha1" - "encoding/hex" - "errors" - "fmt" - "image" - _ "image/jpeg" // support JPEG - _ "image/png" // support PNG - "io" - "net/http" - "os" - "path/filepath" - "sync" - - _ "golang.org/x/image/webp" // support WebP -) - -// CacheEntry représente une image stockée (original + dérivés) -type CacheEntry struct { - PK string `json:"pk"` - SourceURL string `json:"source_url"` - Hits int `json:"hits"` - LastUsed string `json:"last_used"` // ISO8601 -} - -// Cache persistant avec SQLite -type Cache struct { - dir string - limit int - db *DB - - mu sync.Mutex -} - -// NewCache ouvre ou crée un cache persistant avec SQLite -func NewCache(dir string, limit int) (*Cache, error) { - if err := os.MkdirAll(dir, 0o755); err != nil { - return nil, err - } - - db, err := InitDB(dir) - if err != nil { - return nil, err - } - - return &Cache{ - dir: dir, - limit: limit, - db: db, - }, nil -} - -// AddFromURL télécharge une image et la met en cache -func (c *Cache) AddFromURL(url string) (string, error) { - resp, err := http.Get(url) - if err != nil { - return "", err - } - defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - return "", errors.New("bad status") - } - data, err := io.ReadAll(resp.Body) - if err != nil { - return "", err - } - return c.Add(url, data) -} - -// EnsureFromURL vérifie si l'URL est déjà dans le cache et que le fichier existe. -func (c *Cache) EnsureFromURL(url string) (string, error) { - pk := pkFromURL(url) - - // Vérifie si une entrée existe déjà en base - _, err := c.db.Get(pk) - if err == nil { - // Vérifie aussi que le fichier original existe - origPath := filepath.Join(c.dir, pk+".orig.webp") - if _, statErr := os.Stat(origPath); statErr == nil { - return pk, nil - } - // Si le fichier a disparu → on retélécharge - } - - // Sinon, on télécharge et on ajoute - return c.AddFromURL(url) -} - -// decodeImage essaie de décoder une image depuis un []byte en utilisant les formats connus -func decodeImage(data []byte) (image.Image, string, error) { - img, format, err := image.Decode(bytes.NewReader(data)) - if err != nil { - return nil, "", fmt.Errorf("échec de décodage image: %w", err) - } - return img, format, nil -} - -// Add ajoute une image déjà téléchargée -func (c *Cache) Add(url string, data []byte) (string, error) { - pk := pkFromURL(url) - origPath := filepath.Join(c.dir, pk+".orig.webp") - - c.mu.Lock() - defer c.mu.Unlock() - - if _, err := os.Stat(origPath); errors.Is(err, os.ErrNotExist) { - img, format, err := decodeImage(data) - if err != nil { - return "", err - } - fmt.Printf("Décodage réussi : format %s depuis %s\n", format, url) - - buf, err := encodeWebP(img) - if err != nil { - return "", err - } - if err := os.WriteFile(origPath, buf, 0o644); err != nil { - return "", err - } - } - - _ = c.db.Add(pk, url) // ajoute ou met à jour la base - return pk, nil -} - -// Get renvoie le chemin du fichier original et met à jour hits/last_used -func (c *Cache) Get(pk string) (string, error) { - c.mu.Lock() - defer c.mu.Unlock() - - _, err := c.db.Get(pk) - if err != nil { - return "", err - } - - _ = c.db.UpdateHit(pk) - - origPath := filepath.Join(c.dir, pk+".orig.webp") - if _, err := os.Stat(origPath); err != nil { - return "", err - } - return origPath, nil -} - -// Purge vide complètement le cache -func (c *Cache) Purge() error { - c.mu.Lock() - defer c.mu.Unlock() - - files, _ := filepath.Glob(filepath.Join(c.dir, "*")) - for _, f := range files { - os.Remove(f) - } - return c.db.Purge() -} - -// pkFromURL → hash stable basé sur l’URL -func pkFromURL(url string) string { - h := sha1.Sum([]byte(url)) - return hex.EncodeToString(h[:8]) -} - -// Consolidate parcourt la base et corrige les incohérences -func (c *Cache) Consolidate() error { - c.mu.Lock() - defer c.mu.Unlock() - - entries, err := c.db.GetAll() - if err != nil { - return err - } - - // Vérifie chaque entrée de la base - for _, e := range entries { - origPath := filepath.Join(c.dir, e.PK+".orig.webp") - if _, err := os.Stat(origPath); os.IsNotExist(err) { - // Fichier absent → on retente un download - resp, err := http.Get(e.SourceURL) - if err != nil || resp.StatusCode != http.StatusOK { - // Impossible de retélécharger → suppression de l’entrée - _ = c.db.Delete(e.PK) - continue - } - defer resp.Body.Close() - data, _ := io.ReadAll(resp.Body) - if _, err := c.Add(e.SourceURL, data); err != nil { - // Si on échoue quand même → suppression - _ = c.db.Delete(e.PK) - } - } - } - - // Vérifie les fichiers orphelins (qui n’ont pas d’entrée en DB) - files, _ := filepath.Glob(filepath.Join(c.dir, "*.orig.webp")) - for _, f := range files { - pk := filepath.Base(f) - pk = pk[:len(pk)-len(".orig.webp")] - _, err := c.db.Get(pk) - if err != nil { - // Pas d’entrée en DB → supprimer le fichier - _ = os.Remove(f) - } - } - - return nil -} diff --git a/pmocover/db.go b/pmocover/db.go deleted file mode 100644 index 2fba85ac..00000000 --- a/pmocover/db.go +++ /dev/null @@ -1,124 +0,0 @@ -package pmocover - -import ( - "database/sql" - "path/filepath" - "time" - - _ "modernc.org/sqlite" -) - -// DB représente la base SQLite du cache -type DB struct { - conn *sql.DB -} - -// InitDB ouvre ou crée la base SQLite dans le répertoire dir -func InitDB(dir string) (*DB, error) { - path := filepath.Join(dir, "cache.db") - conn, err := sql.Open("sqlite", path) - if err != nil { - return nil, err - } - - db := &DB{conn: conn} - if err := db.initTables(); err != nil { - conn.Close() - return nil, err - } - return db, nil -} - -// initTables crée la table covers si elle n’existe pas -func (db *DB) initTables() error { - _, err := db.conn.Exec(` - CREATE TABLE IF NOT EXISTS covers ( - pk TEXT PRIMARY KEY, - source_url TEXT, - hits INTEGER DEFAULT 0, - last_used TEXT - ); - `) - return err -} - -// Add ajoute ou met à jour une entrée cover -func (db *DB) Add(pk, url string) error { - _, err := db.conn.Exec(` - INSERT INTO covers(pk, source_url, hits, last_used) - VALUES(?, ?, 0, ?) - ON CONFLICT(pk) DO UPDATE SET - source_url=excluded.source_url, - last_used=excluded.last_used; - `, pk, url, time.Now().UTC().Format(time.RFC3339)) - return err -} - -// Get récupère une entrée -func (db *DB) Get(pk string) (*CacheEntry, error) { - row := db.conn.QueryRow(` - SELECT pk, source_url, hits, last_used - FROM covers - WHERE pk = ? - `, pk) - entry := &CacheEntry{} - var lastUsed sql.NullString - err := row.Scan(&entry.PK, &entry.SourceURL, &entry.Hits, &lastUsed) - if err != nil { - return nil, err - } - if lastUsed.Valid { - entry.LastUsed = lastUsed.String - } - return entry, nil -} - -// UpdateHit incrémente hits et met à jour last_used -func (db *DB) UpdateHit(pk string) error { - _, err := db.conn.Exec(` - UPDATE covers - SET hits = hits + 1, - last_used = ? - WHERE pk = ? - `, time.Now().UTC().Format(time.RFC3339), pk) - return err -} - -// Purge supprime toutes les entrées de la base -func (db *DB) Purge() error { - _, err := db.conn.Exec(`DELETE FROM covers`) - return err -} - -// GetAll récupère toutes les entrées triées par hits décroissant -func (db *DB) GetAll() ([]*CacheEntry, error) { - rows, err := db.conn.Query(` - SELECT pk, source_url, hits, last_used - FROM covers - ORDER BY hits DESC - `) - if err != nil { - return nil, err - } - defer rows.Close() - - var entries []*CacheEntry - for rows.Next() { - entry := &CacheEntry{} - var lastUsed sql.NullString - if err := rows.Scan(&entry.PK, &entry.SourceURL, &entry.Hits, &lastUsed); err != nil { - continue - } - if lastUsed.Valid { - entry.LastUsed = lastUsed.String - } - entries = append(entries, entry) - } - return entries, nil -} - -// Delete supprime une entrée spécifique -func (db *DB) Delete(pk string) error { - _, err := db.conn.Exec(`DELETE FROM covers WHERE pk = ?`, pk) - return err -} diff --git a/pmocover/handler.go b/pmocover/handler.go deleted file mode 100644 index 2b807399..00000000 --- a/pmocover/handler.go +++ /dev/null @@ -1,62 +0,0 @@ -package pmocover - -import ( - "encoding/json" - "net/http" - "os" - "path/filepath" - "strconv" - "strings" -) - -// ServeMux branche les routes /covers -func (c *Cache) ServeMux(mux *http.ServeMux) { - // Images - mux.HandleFunc("/covers/images/", func(w http.ResponseWriter, r *http.Request) { - parts := strings.Split(strings.TrimPrefix(r.URL.Path, "/covers/images/"), "/") - if len(parts) == 0 || parts[0] == "" { - http.Error(w, "missing pk", 400) - return - } - pk := parts[0] - if len(parts) == 1 { - path, err := c.Get(pk) - if err != nil { - http.NotFound(w, r) - return - } - w.Header().Set("Content-Type", "image/webp") - http.ServeFile(w, r, path) - return - } - size, err := strconv.Atoi(parts[1]) - if err != nil { - http.Error(w, "invalid size", 400) - return - } - variantPath := filepath.Join(c.dir, pk+"."+parts[1]+".webp") - if _, err := os.Stat(variantPath); os.IsNotExist(err) { - data, err := c.generateVariant(pk, size) - if err != nil { - http.Error(w, "cannot generate", 500) - return - } - w.Header().Set("Content-Type", "image/webp") - w.Write(data) - return - } - w.Header().Set("Content-Type", "image/webp") - http.ServeFile(w, r, variantPath) - }) - - // Stats - mux.HandleFunc("/covers/stats", func(w http.ResponseWriter, r *http.Request) { - entries, err := c.db.GetAll() - if err != nil { - http.Error(w, "cannot retrieve stats", 500) - return - } - w.Header().Set("Content-Type", "application/json") - json.NewEncoder(w).Encode(entries) - }) -} diff --git a/pmocover/pmocover.go b/pmocover/pmocover.go deleted file mode 100644 index 166b5a77..00000000 --- a/pmocover/pmocover.go +++ /dev/null @@ -1,16 +0,0 @@ -package pmocover - -import "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoconfig" - -// GetCoverCache récupère le cache, crée le dossier et la base si nécessaire -func GetCoverCache() (*Cache, error) { - config := pmoconfig.GetConfig() - - dir := config.GetCoverCacheDir() - size := config.GetCoverCacheSize() - cache, err := NewCache(dir, size) - if err != nil { - return nil, err - } - return cache, nil -} diff --git a/pmocover/webp.go b/pmocover/webp.go deleted file mode 100644 index c02e04ee..00000000 --- a/pmocover/webp.go +++ /dev/null @@ -1,87 +0,0 @@ -package pmocover - -import ( - "bytes" - "image" - "image/draw" - "os" - "path/filepath" - "strconv" - - "github.com/chai2010/webp" - xdraw "golang.org/x/image/draw" -) - -// encodeWebP convertit une image.Image en WebP avec compression sans perte. -func encodeWebP(img image.Image) ([]byte, error) { - var buf bytes.Buffer - if err := webp.Encode(&buf, img, &webp.Options{Lossless: true}); err != nil { - return nil, err - } - return buf.Bytes(), nil -} - -// ensureSquare génère une image carrée paddée transparente -func ensureSquare(img image.Image, size int) image.Image { - dst := image.NewRGBA(image.Rect(0, 0, size, size)) - draw.Draw(dst, dst.Bounds(), &image.Uniform{C: image.Transparent}, image.Point{}, draw.Src) - - srcBounds := img.Bounds() - srcW, srcH := srcBounds.Dx(), srcBounds.Dy() - - var scale float64 - if srcW > srcH { - scale = float64(size) / float64(srcW) - } else { - scale = float64(size) / float64(srcH) - } - newW, newH := int(float64(srcW)*scale), int(float64(srcH)*scale) - - // redimensionnement avec Catmull-Rom - tmp := image.NewRGBA(image.Rect(0, 0, newW, newH)) - xdraw.CatmullRom.Scale(tmp, tmp.Bounds(), img, srcBounds, xdraw.Over, nil) - - // centrer l'image redimensionnée dans le carré - offset := image.Pt((size-newW)/2, (size-newH)/2) - draw.Draw(dst, tmp.Bounds().Add(offset), tmp, image.Point{}, draw.Over) - - return dst -} - -// generateVariant génère une version carrée en WebP pour une taille donnée. -// Si le fichier existe déjà, il est renvoyé directement. -func (c *Cache) generateVariant(pk string, size int) ([]byte, error) { - variantPath := filepath.Join(c.dir, pk+"."+strconv.Itoa(size)+".webp") - - // si le variant existe déjà, le renvoyer - if data, err := os.ReadFile(variantPath); err == nil { - return data, nil - } - - // lire l'image originale - origPath := filepath.Join(c.dir, pk+".orig.webp") - data, err := os.ReadFile(origPath) - if err != nil { - return nil, err - } - img, _, err := image.Decode(bytes.NewReader(data)) - if err != nil { - return nil, err - } - - // générer une image carrée - sq := ensureSquare(img, size) - - // encoder en WebP - buf, err := encodeWebP(sq) - if err != nil { - return nil, err - } - - // sauvegarder le variant - if err := os.WriteFile(variantPath, buf, 0o644); err != nil { - return nil, err - } - - return buf, nil -} diff --git a/pmodidl/didilite.go b/pmodidl/didilite.go deleted file mode 100644 index 978a7969..00000000 --- a/pmodidl/didilite.go +++ /dev/null @@ -1,281 +0,0 @@ -package pmodidl - -import ( - "iter" - - "slices" - "strings" - - "gargoton.petite-maison-orange.fr/eric/pmomusic/pmocover" - log "github.com/sirupsen/logrus" -) - -// Méthodes pour DIDLLite - -// CacheAllCoverArts met en cache toutes les images de couverture et stocke les clés primaires -func (d *DIDLLite) CacheAllCoverArts(cache *pmocover.Cache) error { - itemsWithCovers := Filter(d.AllItems(), func(item *Item) bool { - return item.AlbumArt != "" - }) - - for item := range itemsWithCovers { - pk, err := cache.EnsureFromURL(item.AlbumArt) - if err != nil { - log.Errorf("❌ Erreur lors de la mise en cache de %s: %v", item.AlbumArt, err) - continue - } - log.Infof("✅ Mise en cache de %s : pk[%s]", item.AlbumArt, pk) - item.AlbumArtPk = pk - } - - return nil -} - -// AllContainers retourne un itérateur sur tous les containers de manière récursive -func (d *DIDLLite) AllContainers() iter.Seq[*Container] { - return func(yield func(*Container) bool) { - for _, container := range d.Containers { - if !yield(&container) { - return - } - for child := range container.AllContainers() { - if !yield(child) { - return - } - } - } - } -} - -// AllItems retourne un itérateur sur tous les items de manière récursive -func (d *DIDLLite) AllItems() iter.Seq[*Item] { - return func(yield func(*Item) bool) { - for _, item := range d.Items { - if !yield(&item) { - return - } - } - for container := range d.AllContainers() { - for _, item := range container.Items { - if !yield(&item) { - return - } - } - } - } -} - -// GetContainerByID retourne un itérateur sur les containers avec l'ID spécifié -func (d *DIDLLite) GetContainerByID(id string) iter.Seq[*Container] { - return func(yield func(*Container) bool) { - for container := range d.AllContainers() { - if container.ID == id { - if !yield(container) { - return - } - } - } - } -} - -// GetItemByID retourne un itérateur sur les items avec l'ID spécifié -func (d *DIDLLite) GetItemByID(id string) iter.Seq[*Item] { - return func(yield func(*Item) bool) { - for item := range d.AllItems() { - if item.ID == id { - if !yield(item) { - return - } - } - } - } -} - -// FilterContainers filtre les containers selon un prédicat -func (d *DIDLLite) FilterContainers(predicate func(*Container) bool) iter.Seq[*Container] { - return func(yield func(*Container) bool) { - for container := range d.AllContainers() { - if predicate(container) && !yield(container) { - return - } - } - } -} - -// FilterItems filtre les items selon un prédicat -func (d *DIDLLite) FilterItems(predicate func(*Item) bool) iter.Seq[*Item] { - return func(yield func(*Item) bool) { - for item := range d.AllItems() { - if predicate(item) && !yield(item) { - return - } - } - } -} - -// Méthodes pour Container - -// AllContainers retourne un itérateur sur tous les containers enfants de manière récursive -func (c *Container) AllContainers() iter.Seq[*Container] { - return func(yield func(*Container) bool) { - if !yield(c) { - return - } - for _, child := range c.Containers { - for container := range child.AllContainers() { - if !yield(container) { - return - } - } - } - } -} - -// AllItems retourne un itérateur sur tous les items du container et de ses enfants -func (c *Container) AllItems() iter.Seq[*Item] { - return func(yield func(*Item) bool) { - for _, item := range c.Items { - if !yield(&item) { - return - } - } - for _, child := range c.Containers { - for item := range child.AllItems() { - if !yield(item) { - return - } - } - } - } -} - -// GetChildContainers retourne un itérateur sur les containers enfants directs -func (c *Container) GetChildContainers() iter.Seq[*Container] { - return func(yield func(*Container) bool) { - for _, container := range c.Containers { - if !yield(&container) { - return - } - } - } -} - -// GetChildItems retourne un itérateur sur les items directs du container -func (c *Container) GetChildItems() iter.Seq[*Item] { - return func(yield func(*Item) bool) { - for _, item := range c.Items { - if !yield(&item) { - return - } - } - } -} - -// Méthodes pour Item - -// GetAudioResources retourne un itérateur sur les ressources audio -func (i *Item) GetAudioResources() iter.Seq[Res] { - return func(yield func(Res) bool) { - for _, res := range i.Ress { - if strings.HasPrefix(res.ProtocolInfo, "http-get:*:audio/") { - if !yield(res) { - return - } - } - } - } -} - -// GetPrimaryResource retourne la ressource principale (première disponible) -func (i *Item) GetPrimaryResource() iter.Seq[Res] { - return func(yield func(Res) bool) { - if len(i.Ress) > 0 { - if !yield(i.Ress[0]) { - return - } - } - } -} - -// GetMetadata retourne un itérateur sur les métadonnées sous forme de paires clé-valeur -func (i *Item) GetMetadata() iter.Seq2[string, string] { - return func(yield func(string, string) bool) { - if i.Title != "" && !yield("title", i.Title) { - return - } - if i.Artist != "" && !yield("artist", i.Artist) { - return - } - if i.Album != "" && !yield("album", i.Album) { - return - } - if i.Genre != "" && !yield("genre", i.Genre) { - return - } - if i.Date != "" && !yield("date", i.Date) { - return - } - if i.OriginalTrackNumber != "" && !yield("trackNumber", i.OriginalTrackNumber) { - return - } - for _, desc := range i.Descs { - if desc.TrackGain != "" && !yield("replayGain", desc.TrackGain) { - return - } - if desc.TrackPeak != "" && !yield("replayPeak", desc.TrackPeak) { - return - } - } - } -} - -// Fonctions utilitaires - -// Filter filtre une séquence selon un prédicat -func Filter[T any](seq iter.Seq[T], predicate func(T) bool) iter.Seq[T] { - return func(yield func(T) bool) { - for value := range seq { - if predicate(value) && !yield(value) { - return - } - } - } -} - -// Map transforme une séquence en appliquant une fonction -func Map[T, U any](seq iter.Seq[T], f func(T) U) iter.Seq[U] { - return func(yield func(U) bool) { - for value := range seq { - if !yield(f(value)) { - return - } - } - } -} - -// Collect collecte tous les éléments d'une séquence dans une slice -func Collect[T any](seq iter.Seq[T]) []T { - return slices.Collect(seq) -} - -// First retourne le premier élément d'une séquence -func First[T any](seq iter.Seq[T]) (T, bool) { - var zero T - next, stop := iter.Pull(seq) - defer stop() - - value, ok := next() - if !ok { - return zero, false - } - return value, true -} - -// Count compte le nombre d'éléments dans une séquence -func Count[T any](seq iter.Seq[T]) int { - count := 0 - for range seq { - count++ - } - return count -} diff --git a/pmodidl/markdown.go b/pmodidl/markdown.go deleted file mode 100644 index 3ee568c2..00000000 --- a/pmodidl/markdown.go +++ /dev/null @@ -1,129 +0,0 @@ -package pmodidl - -import ( - "fmt" - "strings" -) - -func (d *DIDLLite) ToMarkdown() string { - var buf strings.Builder - buf.WriteString("### DIDL-Lite Document\n\n") - - if len(d.Containers) > 0 { - buf.WriteString("#### Containers\n\n") - for _, c := range d.Containers { - c.markdown(&buf, 0) - } - } - - if len(d.Items) > 0 { - buf.WriteString("#### Items\n\n") - for _, i := range d.Items { - i.markdown(&buf, 0) - } - } - - return buf.String() -} - -func (c *Container) markdown(buf *strings.Builder, depth int) { - indent := strings.Repeat(" ", depth) - - buf.WriteString(fmt.Sprintf("%s- **Container**: %s\n", indent, c.Title)) - buf.WriteString(fmt.Sprintf("%s - ID: `%s`\n", indent, c.ID)) - buf.WriteString(fmt.Sprintf("%s - ParentID: `%s`\n", indent, c.ParentID)) - buf.WriteString(fmt.Sprintf("%s - Class: `%s`\n", indent, c.Class)) - - if c.Restricted != "" { - buf.WriteString(fmt.Sprintf("%s - Restricted: `%s`\n", indent, c.Restricted)) - } - if c.ChildCount != "" { - buf.WriteString(fmt.Sprintf("%s - ChildCount: `%s`\n", indent, c.ChildCount)) - } - - // Sous-conteneurs - if len(c.Containers) > 0 { - buf.WriteString(fmt.Sprintf("%s - Subcontainers:\n", indent)) - for _, sub := range c.Containers { - sub.markdown(buf, depth+2) - } - } - - // Items du conteneur - if len(c.Items) > 0 { - buf.WriteString(fmt.Sprintf("%s - Items:\n", indent)) - for _, item := range c.Items { - item.markdown(buf, depth+2) - } - } - - buf.WriteString("\n") -} - -func (i *Item) markdown(buf *strings.Builder, depth int) { - indent := strings.Repeat(" ", depth) - - buf.WriteString(fmt.Sprintf("%s- **Item**: %s\n", indent, i.Title)) - buf.WriteString(fmt.Sprintf("%s - ID: `%s`\n", indent, i.ID)) - buf.WriteString(fmt.Sprintf("%s - ParentID: `%s`\n", indent, i.ParentID)) - buf.WriteString(fmt.Sprintf("%s - Class: `%s`\n", indent, i.Class)) - - if i.Creator != "" { - buf.WriteString(fmt.Sprintf("%s - Creator: %s\n", indent, i.Creator)) - } - if i.Artist != "" { - buf.WriteString(fmt.Sprintf("%s - Artist: %s\n", indent, i.Artist)) - } - if i.Album != "" { - buf.WriteString(fmt.Sprintf("%s - Album: %s\n", indent, i.Album)) - } - if i.Genre != "" { - buf.WriteString(fmt.Sprintf("%s - Genre: %s\n", indent, i.Genre)) - } - if i.AlbumArt != "" { - buf.WriteString(fmt.Sprintf("%s - Album Art: ![Cover](%s)\n", indent, i.AlbumArt)) - } - if i.Date != "" { - buf.WriteString(fmt.Sprintf("%s - Date: %s\n", indent, i.Date)) - } - if i.OriginalTrackNumber != "" { - buf.WriteString(fmt.Sprintf("%s - Track: %s\n", indent, i.OriginalTrackNumber)) - } - - // Ressources - if len(i.Ress) > 0 { - buf.WriteString(fmt.Sprintf("%s - Resources:\n", indent)) - for _, res := range i.Ress { - buf.WriteString(fmt.Sprintf("%s - URL: %s\n", indent, res.URL)) - buf.WriteString(fmt.Sprintf("%s - Protocol: `%s`\n", indent, res.ProtocolInfo)) - if res.Duration != "" { - buf.WriteString(fmt.Sprintf("%s - Duration: `%s`\n", indent, res.Duration)) - } - if res.BitsPerSample != "" { - buf.WriteString(fmt.Sprintf("%s - BitsPerSample: `%s`\n", indent, res.BitsPerSample)) - } - if res.SampleFrequency != "" { - buf.WriteString(fmt.Sprintf("%s - SampleFrequency: `%s`\n", indent, res.SampleFrequency)) - } - if res.NrAudioChannels != "" { - buf.WriteString(fmt.Sprintf("%s - Channels: `%s`\n", indent, res.NrAudioChannels)) - } - } - } - - // Descriptions - if len(i.Descs) > 0 { - buf.WriteString(fmt.Sprintf("%s - Descriptions:\n", indent)) - for _, desc := range i.Descs { - buf.WriteString(fmt.Sprintf("%s - Namespace: `%s`\n", indent, desc.NameSpace)) - if desc.TrackGain != "" { - buf.WriteString(fmt.Sprintf("%s - Track Gain: `%s`\n", indent, desc.TrackGain)) - } - if desc.TrackPeak != "" { - buf.WriteString(fmt.Sprintf("%s - Track Peak: `%s`\n", indent, desc.TrackPeak)) - } - } - } - - buf.WriteString("\n") -} diff --git a/pmodidl/model.go b/pmodidl/model.go deleted file mode 100644 index faaaef4c..00000000 --- a/pmodidl/model.go +++ /dev/null @@ -1,67 +0,0 @@ -package pmodidl - -import "encoding/xml" - -// DIDLLite représente la racine -type DIDLLite struct { - XMLName xml.Name `xml:"DIDL-Lite"` - Xmlns string `xml:"xmlns,attr"` - XmlnsUpnp string `xml:"xmlns:upnp,attr,omitempty"` - XmlnsDc string `xml:"xmlns:dc,attr,omitempty"` - XmlnsDlna string `xml:"xmlns:dlna,attr,omitempty"` - XmlnsSec string `xml:"xmlns:sec,attr,omitempty"` - XmlnsPv string `xml:"xmlns:pv,attr,omitempty"` - Containers []Container `xml:"container"` - Items []Item `xml:"item"` -} - -// Container peut contenir d'autres containers ou des items audio -type Container struct { - ID string `xml:"id,attr"` - ParentID string `xml:"parentID,attr"` - Restricted string `xml:"restricted,attr,omitempty"` - ChildCount string `xml:"childCount,attr,omitempty"` - Title string `xml:"http://purl.org/dc/elements/1.1/ title"` - Class string `xml:"urn:schemas-upnp-org:metadata-1-0/upnp/ class"` - Containers []Container `xml:"container"` - Items []Item `xml:"item"` -} - -// Item représente un objet audio -type Item struct { - ID string `xml:"id,attr"` - ParentID string `xml:"parentID,attr"` - Restricted string `xml:"restricted,attr,omitempty"` - - Title string `xml:"http://purl.org/dc/elements/1.1/ title"` - Creator string `xml:"http://purl.org/dc/elements/1.1/ creator,omitempty"` - Class string `xml:"urn:schemas-upnp-org:metadata-1-0/upnp/ class"` - Artist string `xml:"urn:schemas-upnp-org:metadata-1-0/upnp/ artist,omitempty"` - Album string `xml:"urn:schemas-upnp-org:metadata-1-0/upnp/ album,omitempty"` - Genre string `xml:"urn:schemas-upnp-org:metadata-1-0/upnp/ genre,omitempty"` - AlbumArt string `xml:"urn:schemas-upnp-org:metadata-1-0/upnp/ albumArtURI,omitempty"` - AlbumArtPk string - Date string `xml:"http://purl.org/dc/elements/1.1/ date,omitempty"` - OriginalTrackNumber string `xml:"urn:schemas-upnp-org:metadata-1-0/upnp/ originalTrackNumber,omitempty"` - - Ress []Res `xml:"res"` - Descs []Desc `xml:"desc"` -} - -// Res correspond aux fichiers média -type Res struct { - ProtocolInfo string `xml:"protocolInfo,attr"` - BitsPerSample string `xml:"bitsPerSample,attr,omitempty"` - SampleFrequency string `xml:"sampleFrequency,attr,omitempty"` - NrAudioChannels string `xml:"nrAudioChannels,attr,omitempty"` - Duration string `xml:"duration,attr,omitempty"` - URL string `xml:",chardata"` -} - -// Desc correspond aux métadonnées optionnelles comme replaygain -type Desc struct { - ID string `xml:"id,attr,omitempty"` - NameSpace string `xml:"nameSpace,attr,omitempty"` - TrackGain string `xml:"track_gain,omitempty"` - TrackPeak string `xml:"track_peak,omitempty"` -} diff --git a/pmodidl/parser.go b/pmodidl/parser.go deleted file mode 100644 index a8a7ebc4..00000000 --- a/pmodidl/parser.go +++ /dev/null @@ -1,26 +0,0 @@ -package pmodidl - -import ( - "encoding/xml" - "fmt" - - "gargoton.petite-maison-orange.fr/eric/pmomusic/pmocover" -) - -func Parse(metadata string) (*DIDLLite, error) { - var didl DIDLLite - err := xml.Unmarshal([]byte(metadata), &didl) - if err != nil { - return nil, fmt.Errorf("failed to parse DIDL-Lite: %v", err) - - } - - cache, err := pmocover.GetCoverCache() - if err != nil { - return &didl, fmt.Errorf("failed to get cover cache: %v", err) - } - - didl.CacheAllCoverArts(cache) - - return &didl, nil -} diff --git a/pmolog/index.html b/pmolog/index.html deleted file mode 100644 index f97a11db..00000000 --- a/pmolog/index.html +++ /dev/null @@ -1,523 +0,0 @@ - - - - - 🚀 Real-Time Logs - - - - - - -
-

📝 Real-Time Logs

-
-
- - - - -
- -
- - - - -
-
-
- - Connecting... - 0 logs -
-
-
- - - \ No newline at end of file diff --git a/pmolog/prettyxml.go b/pmolog/prettyxml.go deleted file mode 100644 index 1c7ced96..00000000 --- a/pmolog/prettyxml.go +++ /dev/null @@ -1,24 +0,0 @@ -package pmolog - -import ( - "bytes" - "encoding/xml" -) - -func PrettyPrintXML(raw string) string { - var out bytes.Buffer - dec := xml.NewDecoder(bytes.NewReader([]byte(raw))) - enc := xml.NewEncoder(&out) - enc.Indent("", " ") - for { - t, err := dec.Token() - if err != nil { - break - } - if err := enc.EncodeToken(t); err != nil { - break - } - } - enc.Flush() - return out.String() -} diff --git a/pmolog/webloger.go b/pmolog/webloger.go deleted file mode 100644 index 62702992..00000000 --- a/pmolog/webloger.go +++ /dev/null @@ -1,197 +0,0 @@ -package pmolog - -import ( - "container/ring" - "context" - "encoding/json" - "fmt" - "net/http" - "strings" - "sync" - "time" - - "github.com/sirupsen/logrus" -) - -const ( - bufferSize = 1000 - clientChanSize = 50 - heartbeatInterval = 15 * time.Second -) - -// ---------- Enhanced SSE Broker ---------- - -type Client struct { - messageChan chan string - filters map[string]bool - searchTerm string -} - -type SSEBroker struct { - clients map[*Client]bool - mu sync.RWMutex -} - -var ( - broker = &SSEBroker{clients: make(map[*Client]bool)} - logBuffer = ring.New(bufferSize) - bufferMutex sync.RWMutex -) - -// ---------- Enhanced Hook for Logrus ---------- - -type SSELogHook struct{} - -func (SSELogHook) Levels() []logrus.Level { return logrus.AllLevels } - -func (SSELogHook) Fire(entry *logrus.Entry) error { - msg := map[string]interface{}{ - "time": time.Now().Format(time.RFC3339Nano), - "level": entry.Level.String(), - "content": entry.Message, - "fields": entry.Data, - } - b, _ := json.Marshal(msg) - - // Add to buffer - bufferMutex.Lock() - logBuffer.Value = string(b) - logBuffer = logBuffer.Next() - bufferMutex.Unlock() - - // Broadcast to clients - broker.mu.RLock() - for client := range broker.clients { - // Apply client-side filtering before sending - if !client.filters[strings.ToLower(msg["level"].(string))] { - continue - } - - if client.searchTerm != "" && - !strings.Contains(strings.ToLower(msg["content"].(string)), client.searchTerm) && - !strings.Contains(strings.ToLower(msg["level"].(string)), client.searchTerm) { - continue - } - - select { - case client.messageChan <- string(b): - default: - // Skip if client channel is full (client is too slow) - } - } - broker.mu.RUnlock() - return nil -} - -// ---------- Enhanced SSE Handler ---------- - -func sseHandler(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "text/event-stream") - w.Header().Set("Cache-Control", "no-cache") - w.Header().Set("Connection", "keep-alive") - w.Header().Set("Access-Control-Allow-Origin", "*") - w.Header().Set("X-Accel-Buffering", "no") // Disable buffering for nginx - - flusher, ok := w.(http.Flusher) - if !ok { - http.Error(w, "Streaming unsupported", http.StatusInternalServerError) - return - } - - // Parse query parameters for initial filters - query := r.URL.Query() - filters := map[string]bool{ - "error": query.Get("error") != "false", - "warning": query.Get("warning") != "false", - "info": query.Get("info") != "false", - "debug": query.Get("debug") != "false", - } - searchTerm := strings.ToLower(query.Get("search")) - - // Create client - client := &Client{ - messageChan: make(chan string, clientChanSize), - filters: filters, - searchTerm: searchTerm, - } - - // Register client - broker.mu.Lock() - broker.clients[client] = true - broker.mu.Unlock() - - // Send initial heartbeat to prevent connection timeout - fmt.Fprintf(w, "event: heartbeat\ndata: %s\n\n", time.Now().Format(time.RFC3339)) - flusher.Flush() - - // Replay buffer - bufferMutex.RLock() - logBuffer.Do(func(v interface{}) { - if v != nil { - // Apply filtering to historical messages - var msg map[string]interface{} - if err := json.Unmarshal([]byte(v.(string)), &msg); err == nil { - if !filters[strings.ToLower(msg["level"].(string))] { - return - } - - if searchTerm != "" && - !strings.Contains(strings.ToLower(msg["content"].(string)), searchTerm) && - !strings.Contains(strings.ToLower(msg["level"].(string)), searchTerm) { - return - } - - fmt.Fprintf(w, "event: message\ndata: %s\n\n", v.(string)) - } - } - }) - flusher.Flush() - bufferMutex.RUnlock() - - // Create a ticker for heartbeats - heartbeat := time.NewTicker(heartbeatInterval) - defer heartbeat.Stop() - - // Stream new messages - for { - select { - case msg := <-client.messageChan: - fmt.Fprintf(w, "event: message\ndata: %s\n\n", msg) - flusher.Flush() - case <-heartbeat.C: - fmt.Fprintf(w, "event: heartbeat\ndata: %s\n\n", time.Now().Format(time.RFC3339)) - flusher.Flush() - case <-r.Context().Done(): - broker.mu.Lock() - delete(broker.clients, client) - broker.mu.Unlock() - close(client.messageChan) - return - } - } -} - -// LoggerWeb installe les routes et arrête le broker quand ctx est annulé. -func LoggerWeb(ctx context.Context, mux *http.ServeMux) { - logrus.SetFormatter(&logrus.TextFormatter{ - ForceColors: true, - FullTimestamp: true, - }) - logrus.AddHook(SSELogHook{}) - - mux.HandleFunc("/log-sse", sseHandler) - - // Goroutine d'arrêt - go func() { - <-ctx.Done() - broker.mu.Lock() - for client := range broker.clients { - close(client.messageChan) - delete(broker.clients, client) - } - broker.mu.Unlock() - logrus.Info("Web logger stopped") - }() - - logrus.Info("Web logger connected at /log") -} diff --git a/pmosoxr/concurency_test.go b/pmosoxr/concurency_test.go deleted file mode 100644 index 241d3fa2..00000000 --- a/pmosoxr/concurency_test.go +++ /dev/null @@ -1,90 +0,0 @@ -//go:build cgo -// +build cgo - -package pmosoxr - -import ( - "math" - "sync" - "testing" - "time" -) - -// genStereoSine génère nFrames frames interlacées float32 (L,R identiques) à amplitude 0.2. -func genStereoSine(nFrames int, freq float64, sr float64) []float32 { - out := make([]float32, nFrames*2) - for i := 0; i < nFrames; i++ { - v := float32(0.2 * math.Sin(2*math.Pi*freq*float64(i)/sr)) - out[2*i] = v - out[2*i+1] = v - } - return out -} - -func TestResamplerConcurrentProcess(t *testing.T) { - inRate := 44100.0 - outRate := 48000.0 - channels := 2 - quality := MQ - - r, err := New(inRate, outRate, channels, quality) - if err != nil { - t.Fatalf("failed to create resampler: %v", err) - } - defer r.Delete() - - workers := 8 - iterations := 200 - framesPerIter := 256 - var wg sync.WaitGroup - errCh := make(chan error, workers) - totalProduced := int64(0) - var prodMu sync.Mutex - - for w := 0; w < workers; w++ { - wg.Add(1) - go func(id int) { - defer wg.Done() - for i := 0; i < iterations; i++ { - in := genStereoSine(framesPerIter, 440.0+float64(id), inRate) - ratio := outRate / inRate - outFrames := int(float64(framesPerIter)*ratio) + 64 - out := make([]float32, outFrames*2) - consumed, produced, perr := r.Process(in, out) - if perr != nil { - errCh <- perr - return - } - if consumed < 0 || produced < 0 { - errCh <- &testError{"negative sample count"} - return - } - if produced > len(out) { - errCh <- &testError{"produced > out buffer"} - return - } - prodMu.Lock() - totalProduced += int64(produced) - prodMu.Unlock() - time.Sleep(1 * time.Millisecond) - } - }(w) - } - - wg.Wait() - close(errCh) - - for e := range errCh { - t.Fatalf("resampler error: %v", e) - } - - if totalProduced == 0 { - t.Fatal("no samples produced") - } -} - -type testError struct { - s string -} - -func (e *testError) Error() string { return e.s } diff --git a/pmosoxr/quality.go b/pmosoxr/quality.go deleted file mode 100644 index b70f2d27..00000000 --- a/pmosoxr/quality.go +++ /dev/null @@ -1,34 +0,0 @@ -package pmosoxr - -/* -#cgo CFLAGS: -I${SRCDIR}/../C/include - -#include -#include - -static soxr_quality_spec_t q_spec(int q) { - switch(q) { - case 0: return soxr_quality_spec(SOXR_QQ, 0); - case 1: return soxr_quality_spec(SOXR_LQ, 0); - case 2: return soxr_quality_spec(SOXR_MQ, 0); - case 3: return soxr_quality_spec(SOXR_HQ, 0); - case 4: return soxr_quality_spec(SOXR_VHQ, 0); - default: return soxr_quality_spec(SOXR_MQ, 0); - } -} -*/ -import "C" - -type Quality int - -const ( - QQ Quality = iota - LQ - MQ - HQ - VHQ -) - -func (q Quality) toC() C.soxr_quality_spec_t { - return C.q_spec(C.int(q)) -} diff --git a/pmosoxr/soxr.go b/pmosoxr/soxr.go deleted file mode 100644 index 1bfcbc30..00000000 --- a/pmosoxr/soxr.go +++ /dev/null @@ -1,124 +0,0 @@ -//go:build cgo -// +build cgo - -package pmosoxr - -/* -#cgo CFLAGS: -I${SRCDIR}/../C/include -#cgo LDFLAGS: ${SRCDIR}/../C/lib/libsoxr.a -lomp - -#include -#include -*/ -import "C" - -import ( - "errors" - "sync" - "unsafe" -) - -type Resampler struct { - handle C.soxr_t - channels int - mu sync.Mutex - deleted bool -} - -func New(inRate, outRate float64, channels int, q Quality) (*Resampler, error) { - if channels != 2 { - return nil, errors.New("only stereo supported") - } - - var err C.soxr_error_t - qspec := q.toC() - - handle := C.soxr_create( - C.double(inRate), - C.double(outRate), - C.uint(channels), - &err, - nil, - &qspec, - nil, - ) - if handle == nil { - if err != nil { - return nil, errors.New(C.GoString(err)) - } - return nil, errors.New("soxr_create failed without error message") - } - return &Resampler{handle: handle, channels: channels}, nil -} - -func (r *Resampler) Process(in []float32, out []float32) (consumedSamples int, producedSamples int, err error) { - r.mu.Lock() - defer r.mu.Unlock() - - if r.deleted { - return 0, 0, errors.New("resampler deleted") - } - if r.handle == nil { - return 0, 0, errors.New("resampler not initialized") - } - if len(in)%r.channels != 0 || len(out)%r.channels != 0 { - return 0, 0, errors.New("buffer size not divisible by channel count") - } - - var idone, odone C.size_t - var inPtr C.soxr_in_t - var outPtr C.soxr_out_t - - if len(in) > 0 { - inPtr = C.soxr_in_t(unsafe.Pointer(&in[0])) - } - if len(out) > 0 { - outPtr = C.soxr_out_t(unsafe.Pointer(&out[0])) - } - - st := C.soxr_process( - r.handle, - inPtr, C.size_t(len(in)/r.channels), - &idone, - outPtr, C.size_t(len(out)/r.channels), - &odone, - ) - if st != nil { - return 0, 0, errors.New(C.GoString(st)) - } - return int(idone) * r.channels, int(odone) * r.channels, nil -} - -func (r *Resampler) Flush(out []float32) (int, error) { - r.mu.Lock() - defer r.mu.Unlock() - - if r.deleted { - return 0, errors.New("resampler deleted") - } - if r.handle == nil { - return 0, errors.New("resampler not initialized") - } - - var odone C.size_t - if len(out) == 0 { - return 0, nil - } - st := C.soxr_process(r.handle, nil, 0, nil, - C.soxr_out_t(unsafe.Pointer(&out[0])), C.size_t(len(out)/r.channels), &odone) - if st != nil { - return 0, errors.New(C.GoString(st)) - } - return int(odone) * r.channels, nil -} - -func (r *Resampler) Delete() { - r.mu.Lock() - defer r.mu.Unlock() - - if !r.deleted && r.handle != nil { - C.soxr_delete(r.handle) - r.handle = nil - r.deleted = true - } -} diff --git a/pmosoxr_test/pmo_soxr_test.go b/pmosoxr_test/pmo_soxr_test.go deleted file mode 100644 index c13bc0d1..00000000 --- a/pmosoxr_test/pmo_soxr_test.go +++ /dev/null @@ -1,94 +0,0 @@ -// pmosoxr/pmosoxr_test.go -//go:build cgo -// +build cgo - -package pmosoxr_test - -import ( - "gargoton.petite-maison-orange.fr/eric/pmomusic/pmosoxr" - "testing" -) - -// TestQualityToC vérifie la conversion des enums Quality vers C -func TestQualityToC_Full(t *testing.T) { - qualities := []pmosoxr.Quality{pmosoxr.QQ, pmosoxr.LQ, pmosoxr.MQ, pmosoxr.HQ, pmosoxr.VHQ} - - for _, q := range qualities { - // Crée un resampler stéréo de 48000->44100 Hz - r, err := pmosoxr.New(48000, 44100, 2, q) - if err != nil { - t.Errorf("Failed to create resampler with quality %v: %v", q, err) - continue - } - - // Remplir un petit buffer d'entrée avec des samples fictifs - in := []float32{0.0, 0.0, 1.0, -1.0, 0.5, -0.5, 0.25, -0.25} - out := make([]float32, len(in)*2) // prévoir assez pour la sortie - - consumed, produced, err := r.Process(in, out) - if err != nil { - t.Errorf("Process failed for quality %v: %v", q, err) - } else { - t.Logf("Quality %v: consumed %d samples, produced %d samples", q, consumed, produced) - } - - // Tester Flush - flushOut := make([]float32, len(out)) - n, err := r.Flush(flushOut) - if err != nil { - t.Errorf("Flush failed for quality %v: %v", q, err) - } else { - t.Logf("Quality %v: flushed %d samples", q, n) - } - - r.Delete() - - } -} - -// TestResamplerCreateDelete vérifie la création et suppression d'un resampler -func TestResamplerCreateDelete(t *testing.T) { - r, err := pmosoxr.New(44100, 48000, 2, pmosoxr.MQ) - if err != nil { - t.Fatalf("failed to create resampler: %v", err) - } - - r.Delete() - -} - -// TestResamplerInvalidChannels vérifie la gestion des canaux non stéréo -func TestResamplerInvalidChannels(t *testing.T) { - _, err := pmosoxr.New(44100, 48000, 1, pmosoxr.MQ) - if err == nil { - t.Fatal("expected error for non-stereo channels") - } -} - -// TestProcessErrors vérifie les erreurs de Process sur buffers invalides -func TestProcessErrors(t *testing.T) { - r, _ := pmosoxr.New(44100, 48000, 2, pmosoxr.MQ) - defer r.Delete() - - _, _, err := r.Process([]float32{0, 1, 2}, []float32{0}) - if err == nil { - t.Fatal("expected error for buffer not divisible by channels") - } - - r.Delete() - _, _, err = r.Process([]float32{0, 1}, []float32{0, 1}) - if err == nil { - t.Fatal("expected error for deleted resampler") - } -} - -// TestFlushEmpty vérifie Flush sur buffer vide -func TestFlushEmpty(t *testing.T) { - r, _ := pmosoxr.New(44100, 48000, 2, pmosoxr.MQ) - defer r.Delete() - - n, err := r.Flush(nil) - if err != nil || n != 0 { - t.Fatalf("Flush empty: got %d, err %v", n, err) - } -} diff --git a/pmosoxr_test/pmosoxr_test.go b/pmosoxr_test/pmosoxr_test.go deleted file mode 100644 index eb518449..00000000 --- a/pmosoxr_test/pmosoxr_test.go +++ /dev/null @@ -1,69 +0,0 @@ -//go:build cgo -// +build cgo - -package pmosoxr_test - -import ( - "sync" - "testing" - - "gargoton.petite-maison-orange.fr/eric/pmomusic/pmosoxr" -) - -// Test création et suppression d'un Resampler -func TestResamplerLifecycle(t *testing.T) { - r, err := pmosoxr.New(44100, 48000, 2, pmosoxr.MQ) - if err != nil { - t.Fatalf("failed to create resampler: %v", err) - } - if r == nil { - t.Fatal("resampler is nil") - } - - in := make([]float32, 512) - out := make([]float32, 512) - consumed, produced, err := r.Process(in, out) - if err != nil { - t.Fatal(err) - } - if consumed < 0 || produced < 0 { - t.Fatal("negative samples") - } - - // Delete multiple fois ne doit pas panique - r.Delete() - r.Delete() -} - -// Test Flush sur un Resampler -func TestResamplerFlush(t *testing.T) { - r, _ := pmosoxr.New(44100, 48000, 2, pmosoxr.MQ) - defer r.Delete() - - buf := make([]float32, 256) - n, err := r.Flush(buf) - if err != nil { - t.Fatal(err) - } - if n < 0 { - t.Fatal("flush returned negative samples") - } -} - -// Concurrence simple -func TestResamplerConcurrent(t *testing.T) { - r, _ := pmosoxr.New(44100, 48000, 2, pmosoxr.MQ) - defer r.Delete() - - var wg sync.WaitGroup - for i := 0; i < 4; i++ { - wg.Add(1) - go func() { - defer wg.Done() - in := make([]float32, 128) - out := make([]float32, 128) - r.Process(in, out) - }() - } - wg.Wait() -} diff --git a/pmostream/audio.go b/pmostream/audio.go deleted file mode 100644 index da7770a1..00000000 --- a/pmostream/audio.go +++ /dev/null @@ -1,60 +0,0 @@ -package pmostream - -import ( - "fmt" - "os" - "strings" - - "github.com/gopxl/beep" - "github.com/gopxl/beep/flac" - "github.com/gopxl/beep/mp3" - "github.com/gopxl/beep/vorbis" - "github.com/gopxl/beep/wav" -) - -type streamerWithCloser struct { - beep.Streamer - closer func() error -} - -func (s *streamerWithCloser) Close() error { - if s.closer != nil { - return s.closer() - } - return nil -} - -func LoadAudio(uri string) (beep.Streamer, beep.Format, error) { - f, err := os.Open(uri) - if err != nil { - return nil, beep.Format{}, err - } - - var streamer beep.Streamer - var format beep.Format - - lowerURI := strings.ToLower(uri) - switch { - case strings.HasSuffix(lowerURI, ".flac"): - streamer, format, err = flac.Decode(f) - case strings.HasSuffix(lowerURI, ".wav"): - streamer, format, err = wav.Decode(f) - case strings.HasSuffix(lowerURI, ".mp3"): - streamer, format, err = mp3.Decode(f) - case strings.HasSuffix(lowerURI, ".ogg"): - streamer, format, err = vorbis.Decode(f) - default: - f.Close() - return nil, beep.Format{}, fmt.Errorf("unsupported format: %s", uri) - } - - if err != nil { - f.Close() - return nil, beep.Format{}, err - } - - return &streamerWithCloser{ - Streamer: streamer, - closer: f.Close, - }, format, nil -} diff --git a/pmostream/buffer.go b/pmostream/buffer.go deleted file mode 100644 index 4bb22987..00000000 --- a/pmostream/buffer.go +++ /dev/null @@ -1,139 +0,0 @@ -package pmostream - -import ( - "sync" - "time" - - log "github.com/sirupsen/logrus" -) - -type AudioBuffer struct { - mu sync.Mutex - cond *sync.Cond - chunks [][]byte - size int - available int - format SampleFormat - readPos int - writePos int - closed bool -} - -func NewAudioBuffer(size int, format SampleFormat) *AudioBuffer { - log.Infof("New AudioBuffer with size %d", size) - ab := &AudioBuffer{ - chunks: make([][]byte, size), - size: size, - format: format, - } - ab.cond = sync.NewCond(&ab.mu) - return ab -} - -func (ab *AudioBuffer) Available() int { - ab.mu.Lock() - defer ab.mu.Unlock() - return ab.available -} - -// Write ajoute un chunk dans le buffer (écrase le plus ancien si plein) -func (ab *AudioBuffer) Write(chunk []byte) { - ab.mu.Lock() - defer ab.mu.Unlock() - if ab.closed { - return - } - - ab.chunks[ab.writePos] = chunk - ab.writePos = (ab.writePos + 1) % ab.size - - if ab.available < ab.size { - ab.available++ - } else { - // tampon plein, on écrase → avancer readPos - ab.readPos = (ab.readPos + 1) % ab.size - } - - ab.cond.Broadcast() -} - -func (ab *AudioBuffer) Read() []byte { - ab.mu.Lock() - defer ab.mu.Unlock() - - if ab.available == 0 { - return nil - } - - chunk := ab.chunks[ab.readPos] - ab.chunks[ab.readPos] = nil - ab.readPos = (ab.readPos + 1) % ab.size - ab.available-- - - return chunk -} - -// WaitForData attend qu'au moins n chunks soient disponibles ou timeout/closed -func (ab *AudioBuffer) WaitForData(n int, timeout time.Duration) bool { - ab.mu.Lock() - defer ab.mu.Unlock() - - if n <= 0 { - n = 1 - } - - if timeout <= 0 { - for ab.available < n && !ab.closed { - ab.cond.Wait() - } - return ab.available >= n && !ab.closed - } - - deadline := time.Now().Add(timeout) - for ab.available < n && !ab.closed { - remaining := time.Until(deadline) - if remaining <= 0 { - return false - } - waitCondWithTimeout(ab.cond, remaining) - } - - return ab.available >= n && !ab.closed -} - -// Wait est un raccourci pour WaitForData(1, 0) -func (ab *AudioBuffer) Wait() { - ab.WaitForData(1, 0) -} - -func (ab *AudioBuffer) Close() { - ab.mu.Lock() - defer ab.mu.Unlock() - if !ab.closed { - ab.closed = true - ab.cond.Broadcast() - } -} - -// Fonction helper pour attendre une sync.Cond avec timeout -func waitCondWithTimeout(c *sync.Cond, d time.Duration) bool { - timer := time.NewTimer(d) - done := make(chan struct{}) - - go func() { - c.L.Lock() - defer c.L.Unlock() - c.Wait() - close(done) - }() - - select { - case <-done: - if !timer.Stop() { - <-timer.C - } - return true - case <-timer.C: - return false - } -} diff --git a/pmostream/conversion.go b/pmostream/conversion.go deleted file mode 100644 index 85f404f1..00000000 --- a/pmostream/conversion.go +++ /dev/null @@ -1,88 +0,0 @@ -package pmostream - -import ( - "encoding/binary" - "math" -) - -func ConvertFloat64ToFloat32(samples [][2]float64) []float32 { - if len(samples) == 0 { - return nil - } - result := make([]float32, len(samples)*2) - for i, s := range samples { - result[2*i] = float32(clamp(s[0], -1.0, 1.0)) - result[2*i+1] = float32(clamp(s[1], -1.0, 1.0)) - } - return result -} - -func ConvertFloat64ToPCM(samples [][2]float64) []byte { - if len(samples) == 0 { - return nil - } - buf := make([]byte, len(samples)*4) - for i, s := range samples { - l := int16(clamp(s[0], -1.0, 1.0) * 32767.0) - r := int16(clamp(s[1], -1.0, 1.0) * 32767.0) - binary.LittleEndian.PutUint16(buf[4*i:], uint16(uint16(l))) - binary.LittleEndian.PutUint16(buf[4*i+2:], uint16(uint16(r))) - } - return buf -} - -func Float32ToPCM(samples []float32) []byte { - if len(samples) == 0 { - return nil - } - buf := make([]byte, len(samples)*2) - for i, v := range samples { - val := int16(clamp(float64(v), -1.0, 1.0) * 32767.0) - binary.LittleEndian.PutUint16(buf[2*i:], uint16(val)) - } - return buf -} - -func Float32ToBytes(samples []float32) []byte { - if len(samples) == 0 { - return nil - } - buf := make([]byte, len(samples)*4) - for i, v := range samples { - binary.LittleEndian.PutUint32(buf[i*4:], math.Float32bits(v)) - } - return buf -} - -func BytesToFloat32(data []byte) []float32 { - if len(data)%4 != 0 { - return nil - } - result := make([]float32, len(data)/4) - for i := range result { - result[i] = math.Float32frombits(binary.LittleEndian.Uint32(data[i*4:])) - } - return result -} - -func PcmToFloat32(data []byte) []float32 { - if len(data)%2 != 0 { - return nil - } - result := make([]float32, len(data)/2) - for i := 0; i < len(result); i++ { - val := int16(binary.LittleEndian.Uint16(data[2*i:])) - result[i] = float32(val) / 32768.0 - } - return result -} - -func clamp(val, min, max float64) float64 { - if val < min { - return min - } - if val > max { - return max - } - return val -} diff --git a/pmostream/core.go b/pmostream/core.go deleted file mode 100644 index 825c02ab..00000000 --- a/pmostream/core.go +++ /dev/null @@ -1,271 +0,0 @@ -package pmostream - -import ( - "fmt" - "math" - "sync" - "sync/atomic" - "time" - - "gargoton.petite-maison-orange.fr/eric/pmomusic/pmosoxr" - "github.com/gopxl/beep" - "github.com/gopxl/beep/effects" -) - -type SampleFormat int - -const ( - Float32 SampleFormat = iota - PCM16 -) - -type HiFiConfig struct { - TargetSampleRate beep.SampleRate - BufferSeconds int - ChunkSize int - ResampleQuality pmosoxr.Quality - Volume float64 - Format SampleFormat -} - -func DefaultHiFiConfig() HiFiConfig { - return HiFiConfig{ - TargetSampleRate: 48000, - BufferSeconds: 5, - ChunkSize: 1024, - ResampleQuality: pmosoxr.HQ, - Volume: 0.0, - Format: PCM16, - } -} - -type AudioProcessor struct { - config HiFiConfig - streamer beep.Streamer - format beep.Format - resampler *pmosoxr.Resampler - volume *effects.Volume - volumeValue float64 - buffer *AudioBuffer - masterBuffer *MasterBuffer - processMutex sync.Mutex - running atomic.Bool - wg sync.WaitGroup - resampleBuf []float32 - volumeMu sync.Mutex - streamDone atomic.Bool -} - -func NewAudioProcessor(streamer beep.Streamer, format beep.Format, config HiFiConfig, master *MasterBuffer) (*AudioProcessor, error) { - if streamer == nil && master == nil { - return nil, fmt.Errorf("streamer cannot be nil if no master buffer is provided") - } - - if format.NumChannels != 2 { - return nil, fmt.Errorf("only stereo format is supported") - } - - var vol *effects.Volume - if streamer != nil { - vol = &effects.Volume{ - Streamer: streamer, - Base: 2, - Volume: config.Volume, - Silent: false, - } - } - - var resampler *pmosoxr.Resampler - var err error - if streamer != nil && format.SampleRate != config.TargetSampleRate { - resampler, err = pmosoxr.New(float64(format.SampleRate), float64(config.TargetSampleRate), 2, config.ResampleQuality) - if err != nil { - return nil, fmt.Errorf("failed to create resampler: %w", err) - } - } - - sampleSize := 4 - if config.Format == PCM16 { - sampleSize = 2 - } - bytesPerSecond := int(config.TargetSampleRate) * sampleSize * 2 // stéréo - bufferSize := (bytesPerSecond * config.BufferSeconds) / config.ChunkSize - if bufferSize < 1 { - bufferSize = 1 - } - - ap := &AudioProcessor{ - config: config, - streamer: streamer, - format: format, - resampler: resampler, - volume: vol, - volumeValue: config.Volume, - buffer: NewAudioBuffer(bufferSize, config.Format), - masterBuffer: master, - } - ap.running.Store(true) - return ap, nil -} - -func (p *AudioProcessor) GetBuffer() *AudioBuffer { - return p.buffer -} - -func (p *AudioProcessor) SetVolume(volume float64) { - p.volumeMu.Lock() - defer p.volumeMu.Unlock() - p.volumeValue = volume - if p.volume != nil { - p.volume.Volume = volume - } -} - -func (p *AudioProcessor) Stop() { - p.running.Store(false) -} - -func (p *AudioProcessor) Close() error { - p.Stop() - p.wg.Wait() - p.processMutex.Lock() - defer p.processMutex.Unlock() - - if p.resampler != nil { - p.resampler.Delete() - } - if closer, ok := p.streamer.(interface{ Close() error }); ok { - return closer.Close() - } - return nil -} - -// Process lit depuis le streamer ou le master buffer, applique resampling + volume et écrit dans le buffer -func (p *AudioProcessor) Process() error { - if !p.running.Load() { - return nil - } - - p.wg.Add(1) - defer p.wg.Done() - - chunkSize := p.config.ChunkSize - if chunkSize <= 0 { - chunkSize = 1024 - } - - for p.running.Load() { - var samples [][2]float64 - - // 1) Lire depuis le streamer - if p.streamer != nil { - samples = make([][2]float64, chunkSize) - n, ok := p.streamer.Stream(samples) - if !ok { - p.streamDone.Store(true) - break - } - samples = samples[:n] - if n == 0 { - time.Sleep(5 * time.Millisecond) - continue - } - } else if p.masterBuffer != nil { - // Lecture via ForkedBuffer - chunks := p.masterBuffer.ReadAll() - if len(chunks) == 0 { - time.Sleep(5 * time.Millisecond) - continue - } - - samples = make([][2]float64, 0) - for _, c := range chunks { - var fs []float32 - if p.config.Format == Float32 { - fs = BytesToFloat32(c) - } else { - fs = PcmToFloat32(c) - } - if len(fs)%2 != 0 { - continue - } - for i := 0; i < len(fs); i += 2 { - samples = append(samples, [2]float64{float64(fs[i]), float64(fs[i+1])}) - } - } - if len(samples) == 0 { - time.Sleep(5 * time.Millisecond) - continue - } - } else { - time.Sleep(5 * time.Millisecond) - continue - } - - // 2) Resampler si nécessaire - var processed []float32 - if p.resampler != nil { - if len(p.resampleBuf) < len(samples)*2 { - p.resampleBuf = make([]float32, len(samples)*2) - } - inBuf := ConvertFloat64ToFloat32(samples) - _, np, err := p.resampler.Process(inBuf, p.resampleBuf) - if err != nil { - return err - } - processed = p.resampleBuf[:np] - } else { - processed = ConvertFloat64ToFloat32(samples) - } - - // 3) Appliquer volume - p.volumeMu.Lock() - volumeFactor := float32(math.Pow(2, p.volumeValue)) - p.volumeMu.Unlock() - for i := range processed { - processed[i] *= volumeFactor - } - - // 4) Convertir et écrire - var chunk []byte - if p.config.Format == Float32 { - chunk = Float32ToBytes(processed) - } else { - chunk = Float32ToPCM(processed) - } - p.buffer.Write(chunk) - } - - // Flush resampler à la fin uniquement - if p.resampler != nil { - flushBuf := make([]float32, 4096) - for { - _, np, err := p.resampler.Process(nil, flushBuf) - if err != nil { - return err - } - if np == 0 { - break - } - - processed := flushBuf[:np] - p.volumeMu.Lock() - volumeFactor := float32(math.Pow(2, p.volumeValue)) - p.volumeMu.Unlock() - for i := range processed { - processed[i] *= volumeFactor - } - - var chunk []byte - if p.config.Format == Float32 { - chunk = Float32ToBytes(processed) - } else { - chunk = Float32ToPCM(processed) - } - p.buffer.Write(chunk) - } - } - - p.buffer.Close() // fermer uniquement à la fin - return nil -} diff --git a/pmostream/fork.go b/pmostream/fork.go deleted file mode 100644 index 7f484641..00000000 --- a/pmostream/fork.go +++ /dev/null @@ -1,208 +0,0 @@ -package pmostream - -import ( - "fmt" - "sync" - "time" - - "github.com/gopxl/beep" -) - -// MasterBuffer est un buffer central qui permet de fork un flux vers plusieurs processors -type MasterBuffer struct { - mu sync.RWMutex - cond *sync.Cond - chunks [][]byte - closed bool -} - -// NewMasterBuffer crée un buffer central -func NewMasterBuffer() *MasterBuffer { - mb := &MasterBuffer{} - mb.cond = sync.NewCond(&mb.mu) - return mb -} - -// Write ajoute un chunk au buffer central -func (mb *MasterBuffer) Write(chunk []byte) { - if len(chunk) == 0 { - return - } - - mb.mu.Lock() - defer mb.mu.Unlock() - - if mb.closed { - return - } - - data := make([]byte, len(chunk)) - copy(data, chunk) - - mb.chunks = append(mb.chunks, data) - mb.cond.Broadcast() -} - -// Fork crée un lecteur indépendant pour ce buffer -func (mb *MasterBuffer) Fork() *ForkedBuffer { - mb.mu.RLock() - defer mb.mu.RUnlock() - - return &ForkedBuffer{ - master: mb, - index: len(mb.chunks), - } -} - -// Close ferme le buffer et notifie tous les lecteurs -func (mb *MasterBuffer) Close() { - mb.mu.Lock() - defer mb.mu.Unlock() - mb.closed = true - mb.cond.Broadcast() -} - -// ForkedBuffer permet à un processor forké de lire indépendamment -type ForkedBuffer struct { - master *MasterBuffer - index int -} - -func (fb *ForkedBuffer) ReadAll() [][]byte { - fb.master.mu.Lock() // Lock au lieu de RLock - defer fb.master.mu.Unlock() - - if fb.index >= len(fb.master.chunks) { - return nil - } - - result := make([][]byte, len(fb.master.chunks)-fb.index) - for i := fb.index; i < len(fb.master.chunks); i++ { - result[i-fb.index] = fb.master.chunks[i] - } - fb.index = len(fb.master.chunks) - return result -} - -func (fb *ForkedBuffer) WaitForData(timeoutMs int) bool { - deadline := time.Now().Add(time.Duration(timeoutMs) * time.Millisecond) - fb.master.mu.Lock() - defer fb.master.mu.Unlock() - - for fb.index >= len(fb.master.chunks) && !fb.master.closed { - remaining := time.Until(deadline) - if remaining <= 0 { - return false - } - fb.master.cond.Wait() - } - return fb.index < len(fb.master.chunks) -} - -// ForkStreamer crée plusieurs streamers à partir d'un streamer source en utilisant un MasterBuffer -func ForkStreamer(streamer beep.Streamer, format beep.Format, config HiFiConfig, nForks int) ([]beep.Streamer, error) { - if nForks < 1 { - return nil, fmt.Errorf("nForks must be at least 1") - } - - // Créer un MasterBuffer - master := NewMasterBuffer() - - // Créer un processeur principal qui alimente le MasterBuffer - mainProc, err := NewAudioProcessor(streamer, format, config, master) - if err != nil { - return nil, err - } - - // Démarrer le traitement principal - go mainProc.Process() - - // Créer des streamers forké - forks := make([]beep.Streamer, nForks) - for i := 0; i < nForks; i++ { - forkedBuffer := master.Fork() - forks[i] = &forkedStreamer{ - fb: forkedBuffer, - config: config, - } - } - - return forks, nil -} - -// forkedStreamer implémente beep.Streamer pour lire depuis un ForkedBuffer -type forkedStreamer struct { - fb *ForkedBuffer - config HiFiConfig -} - -func (fs *forkedStreamer) Stream(samples [][2]float64) (n int, ok bool) { - if !fs.fb.WaitForData(100) { - return 0, true - } - - chunks := fs.fb.ReadAll() - if len(chunks) == 0 { - return 0, true - } - - // Concaténer tous les chunks - var totalSize int - for _, chunk := range chunks { - totalSize += len(chunk) - } - - combined := make([]byte, 0, totalSize) - for _, chunk := range chunks { - combined = append(combined, chunk...) - } - - // Convertir en float32 selon le format - var allData []float32 - if fs.config.Format == Float32 { - allData = BytesToFloat32(combined) - } else { - allData = PcmToFloat32(combined) - } - - if allData == nil { - return 0, true - } - - numSamples := len(allData) / 2 - if numSamples > len(samples) { - numSamples = len(samples) - } - - for i := 0; i < numSamples; i++ { - if 2*i+1 < len(allData) { - samples[i][0] = float64(allData[2*i]) - samples[i][1] = float64(allData[2*i+1]) - } - } - - return numSamples, true -} - -func (fs *forkedStreamer) Err() error { - return nil -} - -// ReadAll retourne tous les chunks disponibles dans le buffer central -func (mb *MasterBuffer) ReadAll() [][]byte { - mb.mu.RLock() - defer mb.mu.RUnlock() - - if mb.closed || len(mb.chunks) == 0 { - return nil - } - - // Créer une copie de tous les chunks - result := make([][]byte, len(mb.chunks)) - for i, chunk := range mb.chunks { - result[i] = make([]byte, len(chunk)) - copy(result[i], chunk) - } - - return result -} diff --git a/pmostream/fork_eq_test.go b/pmostream/fork_eq_test.go deleted file mode 100644 index fd25242a..00000000 --- a/pmostream/fork_eq_test.go +++ /dev/null @@ -1,47 +0,0 @@ -//go:build cgo -// +build cgo - -package pmostream - -import ( - "math" - "testing" - "time" - - "github.com/gopxl/beep" -) - -// TestForkedEQ vérifie que chaque fork peut avoir son propre ParametricEQ appliqué -func TestAudioProcessorWithMasterBuffer(t *testing.T) { - stream := beep.StreamerFunc(func(samples [][2]float64) (n int, ok bool) { - for i := range samples { - v := 0.2 * math.Sin(2*math.Pi*440*float64(i)/44100.0) - samples[i][0] = v - samples[i][1] = v - } - return len(samples), true - }) - - format := beep.Format{SampleRate: 44100, NumChannels: 2, Precision: 2} - config := DefaultHiFiConfig() - master := NewMasterBuffer() - - proc, err := NewAudioProcessor(stream, format, config, master) - if err != nil { - t.Fatal(err) - } - - go proc.Process() - defer proc.Close() - - time.Sleep(50 * time.Millisecond) - - if proc.buffer.Available() == 0 { - t.Fatal("buffer should contain data") - } - - chunk := proc.buffer.Read() - if chunk == nil || len(chunk) == 0 { - t.Fatal("failed to read chunk from buffer") - } -} diff --git a/pmostream/parameq.go b/pmostream/parameq.go deleted file mode 100644 index ab1ed60d..00000000 --- a/pmostream/parameq.go +++ /dev/null @@ -1,93 +0,0 @@ -package pmostream - -import ( - "math" - "sync" - - "github.com/gopxl/beep" -) - -// ParametricEQ applique un égaliseur paramétrique stéréo (Biquad peaking) sur un Streamer. -type ParametricEQ struct { - input beep.Streamer - sampleRate float64 - mu sync.Mutex - - // Coefficients Biquad - a0, a1, a2, b1, b2 float64 - - // États pour les deux canaux - x1, x2, y1, y2 [2]float64 -} - -// EQParams définit les paramètres d'un filtre peaking -type EQParams struct { - FreqHz float64 // fréquence centrale en Hz - GainDB float64 // gain en dB - Q float64 // facteur de qualité -} - -// NewParametricEQ construit un EQ peaking stéréo en interrogeant le streamer pour la fréquence -func NewParametricEQ(input beep.Streamer, params EQParams, sr beep.SampleRate) *ParametricEQ { - eq := &ParametricEQ{ - input: input, - sampleRate: float64(sr), - } - - eq.setParams(params) - return eq -} - -// setParams calcule les coefficients du Biquad -func (eq *ParametricEQ) setParams(p EQParams) { - eq.mu.Lock() - defer eq.mu.Unlock() - - A := math.Pow(10, p.GainDB/40) // conversion dB -> amplitude - w0 := 2 * math.Pi * p.FreqHz / eq.sampleRate - alpha := math.Sin(w0) / (2 * p.Q) - - a0 := 1 + alpha/A - eq.a0 = 1 - eq.a1 = -2 * math.Cos(w0) / a0 - eq.a2 = (1 - alpha/A) / a0 - eq.b1 = 2 * math.Cos(w0) * -1 / a0 - eq.b2 = (1 - alpha*A) / a0 -} - -// Stream applique l'EQ sur un chunk stéréo float64 [][2]float64 -func (eq *ParametricEQ) Stream(samples [][2]float64) (n int, ok bool) { - eq.mu.Lock() - defer eq.mu.Unlock() - - if len(samples) == 0 { - return 0, true - } - - for i := range samples { - for ch := 0; ch < 2; ch++ { - x := samples[i][ch] - y := eq.a0*x + eq.a1*eq.x1[ch] + eq.a2*eq.x2[ch] - eq.b1*eq.y1[ch] - eq.b2*eq.y2[ch] - - eq.x2[ch] = eq.x1[ch] - eq.x1[ch] = x - eq.y2[ch] = eq.y1[ch] - eq.y1[ch] = y - - samples[i][ch] = y - } - } - return len(samples), true -} - -// Close libère les ressources (pas nécessaire ici mais pour interface uniforme) -func (eq *ParametricEQ) Close() error { - return nil -} - -// Wrap permet d'utiliser ParametricEQ comme beep.Streamer -func (eq *ParametricEQ) Streamer() beep.Streamer { - return beep.StreamerFunc(func(samples [][2]float64) (n int, ok bool) { - return eq.Stream(samples) - }) -} diff --git a/pmostream/streamer.go b/pmostream/streamer.go deleted file mode 100644 index e5220411..00000000 --- a/pmostream/streamer.go +++ /dev/null @@ -1,150 +0,0 @@ -package pmostream - -import ( - "encoding/binary" - "log" - "net/http" - "sync" - "time" - - "github.com/gopxl/beep" -) - -// StreamManager gère plusieurs AudioProcessor et clients HTTP -type StreamManager struct { - processors map[string]*AudioProcessor - mu sync.RWMutex -} - -// NewStreamManager crée un gestionnaire de flux audio -func NewStreamManager() *StreamManager { - return &StreamManager{ - processors: make(map[string]*AudioProcessor), - } -} - -// AddProcessor ajoute un processeur audio et démarre sa boucle Process -func (m *StreamManager) AddProcessor(id string, processor *AudioProcessor) { - m.mu.Lock() - defer m.mu.Unlock() - - if _, exists := m.processors[id]; exists { - log.Printf("Processor with id %s already exists", id) - return - } - m.processors[id] = processor - - go func() { - if err := processor.Process(); err != nil { - log.Printf("Processor error for %s: %v", id, err) - } - }() -} - -// RemoveProcessor arrête et supprime un processeur audio -func (m *StreamManager) RemoveProcessor(id string) { - m.mu.Lock() - defer m.mu.Unlock() - - if processor, exists := m.processors[id]; exists { - processor.Stop() - processor.Close() - delete(m.processors, id) - } -} - -// GetHandler retourne un handler HTTP pour streamer un flux audio -func (m *StreamManager) GetHandler(id string) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - m.mu.RLock() - processor, exists := m.processors[id] - m.mu.RUnlock() - - if !exists { - http.Error(w, "Stream not found", http.StatusNotFound) - return - } - - buffer := processor.GetBuffer() - config := processor.config - - w.Header().Set("Content-Type", "audio/wav") - w.Header().Set("Cache-Control", "no-cache") - w.Header().Set("Connection", "keep-alive") - w.Header().Set("Access-Control-Allow-Origin", "*") - - flusher, ok := w.(http.Flusher) - if !ok { - http.Error(w, "Streaming not supported", http.StatusInternalServerError) - return - } - - // Écrire l'en-tête WAV pour streaming - if err := writeWavHeader(w, config.TargetSampleRate, config.Format); err != nil { - log.Printf("Failed to write WAV header: %v", err) - return - } - flusher.Flush() - - clientDone := r.Context().Done() - - for { - select { - case <-clientDone: - log.Printf("Client disconnected: %s", id) - return - default: - } - - // Attendre les données avec timeout - if !buffer.WaitForData(1, 100*time.Millisecond) { - continue - } - - chunk := buffer.Read() - if chunk == nil { - continue - } - - // Envoyer le chunk au client - if _, err := w.Write(chunk); err != nil { - log.Printf("Write error: %v", err) - return - } - flusher.Flush() - } - } -} - -// writeWavHeader écrit un en-tête WAV pour streaming -func writeWavHeader(w http.ResponseWriter, sampleRate beep.SampleRate, format SampleFormat) error { - var audioFormat uint16 = 1 // PCM - var bitsPerSample uint16 = 16 - - if format == Float32 { - audioFormat = 3 // IEEE_FLOAT - bitsPerSample = 32 - } - - numChannels := uint16(2) - blockAlign := numChannels * bitsPerSample / 8 - byteRate := uint32(sampleRate) * uint32(blockAlign) - - header := make([]byte, 44) - copy(header[0:4], "RIFF") - binary.LittleEndian.PutUint32(header[4:8], 0xFFFFFFFF) // Taille inconnue pour streaming - copy(header[8:12], "WAVE") - copy(header[12:16], "fmt ") - binary.LittleEndian.PutUint32(header[16:20], 16) - binary.LittleEndian.PutUint16(header[20:22], audioFormat) - binary.LittleEndian.PutUint16(header[22:24], numChannels) - binary.LittleEndian.PutUint32(header[24:28], uint32(sampleRate)) - binary.LittleEndian.PutUint32(header[28:32], byteRate) - binary.LittleEndian.PutUint16(header[32:34], blockAlign) - binary.LittleEndian.PutUint16(header[34:36], bitsPerSample) - copy(header[36:40], "data") - binary.LittleEndian.PutUint32(header[40:44], 0xFFFFFFFF) // Taille inconnue pour streaming - - _, err := w.Write(header) - return err -} diff --git a/pmostream_test/pmostream_test.go b/pmostream_test/pmostream_test.go deleted file mode 100644 index 0b71ea7a..00000000 --- a/pmostream_test/pmostream_test.go +++ /dev/null @@ -1,131 +0,0 @@ -package pmostream_test - -import ( - "testing" - "time" - - "gargoton.petite-maison-orange.fr/eric/pmomusic/pmostream" - "github.com/gopxl/beep" -) - -// ----------------------- Audio conversions ------------------------ -func TestConvertFloat64ToFloat32(t *testing.T) { - in := [][2]float64{{-2, 2}, {0.5, -0.5}} - out := pmostream.ConvertFloat64ToFloat32(in) - if len(out) != 4 { - t.Fatal("unexpected length") - } - if out[0] != -1 || out[1] != 1 { - t.Fatal("clamp failed") - } -} - -func TestFloat32ToPCM(t *testing.T) { - in := []float32{0.5, -0.5} - buf := pmostream.Float32ToPCM(in) - if len(buf) != 4 { - t.Fatal("length wrong") - } -} - -func TestFloat32ToBytesAndBack(t *testing.T) { - in := []float32{0.1, -0.2, 0.3} - b := pmostream.Float32ToBytes(in) - out := pmostream.BytesToFloat32(b) - if len(out) != len(in) { - t.Fatal("length mismatch") - } -} - -// ----------------------- AudioBuffer ------------------------ -func TestAudioBufferWriteRead(t *testing.T) { - buf := pmostream.NewAudioBuffer(2, pmostream.PCM16) - data := []byte{1, 2, 3} - buf.Write(data) - if buf.Available() != 1 { - t.Fatal("available wrong") - } - r := buf.Read() - if string(r) != string(data) { - t.Fatal("read content mismatch") - } -} - -func TestAudioBufferOverwrite(t *testing.T) { - buf := pmostream.NewAudioBuffer(2, pmostream.PCM16) - buf.Write([]byte{1}) - buf.Write([]byte{2}) - buf.Write([]byte{3}) // overwrite - if buf.Available() != 2 { - t.Fatal("overwrite failed") - } -} - -// ----------------------- MasterBuffer & ForkedBuffer ------------------------ -func TestMasterBufferFork(t *testing.T) { - m := pmostream.NewMasterBuffer() - m.Write([]byte{1, 2}) - f := m.Fork() - chunks := f.ReadAll() - if len(chunks) != 1 { - t.Fatal("fork readall failed") - } -} - -// ----------------------- ParametricEQ ------------------------ -func TestParametricEQ(t *testing.T) { - stream := beep.StreamerFunc(func(samples [][2]float64) (int, bool) { - for i := range samples { - samples[i][0] = 1 - samples[i][1] = 1 - } - return len(samples), true - }) - eq := pmostream.NewParametricEQ(stream, pmostream.EQParams{FreqHz: 440, GainDB: 3, Q: 1}, 44100) - buf := make([][2]float64, 10) - n, ok := eq.Stream(buf) - if !ok || n != 10 { - t.Fatal("stream failed") - } -} - -// ----------------------- AudioProcessor ------------------------ -func TestAudioProcessorInit(t *testing.T) { - stream := beep.StreamerFunc(func(samples [][2]float64) (int, bool) { return len(samples), true }) - format := beep.Format{SampleRate: 44100, NumChannels: 2, Precision: 2} - config := pmostream.DefaultHiFiConfig() - proc, err := pmostream.NewAudioProcessor(stream, format, config, nil) - if err != nil { - t.Fatal(err) - } - proc.SetVolume(1.0) - proc.Stop() - proc.Close() -} - -// ----------------------- StreamManager ------------------------ -func TestStreamManagerAddRemove(t *testing.T) { - m := pmostream.NewStreamManager() - stream := beep.StreamerFunc(func(samples [][2]float64) (int, bool) { return len(samples), true }) - format := beep.Format{SampleRate: 44100, NumChannels: 2, Precision: 2} - config := pmostream.DefaultHiFiConfig() - proc, _ := pmostream.NewAudioProcessor(stream, format, config, nil) - m.AddProcessor("p1", proc) - m.RemoveProcessor("p1") -} - -// ----------------------- LoadAudio ------------------------ -func TestLoadAudioUnsupported(t *testing.T) { - _, _, err := pmostream.LoadAudio("file.unsupported") - if err == nil { - t.Fatal("expected error") - } -} - -// ----------------------- WaitForData with timeout ------------------------ -func TestAudioBufferWaitForDataTimeout(t *testing.T) { - buf := pmostream.NewAudioBuffer(2, pmostream.PCM16) - if buf.WaitForData(1, 10*time.Millisecond) { - t.Fatal("should timeout") - } -} diff --git a/pmoupnp/debug_index.go b/pmoupnp/debug_index.go deleted file mode 100644 index 8e7e0337..00000000 --- a/pmoupnp/debug_index.go +++ /dev/null @@ -1,35 +0,0 @@ -package pmoupnp - -import ( - "fmt" - "html" - "net/http" -) - -func (s *Server) ServeDebugIndex(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "text/html; charset=utf-8") - - fmt.Fprintf(w, ` - - - - UPnP Debug Interface - - - -

Host %s

-

address: %s

`, - s.Name(), - html.EscapeString(html.EscapeString(s.BaseURL()))) - - fmt.Fprint(w, ` - - -`) -} diff --git a/pmoupnp/dev_set.go b/pmoupnp/dev_set.go deleted file mode 100644 index 98fd875c..00000000 --- a/pmoupnp/dev_set.go +++ /dev/null @@ -1,36 +0,0 @@ -package pmoupnp - -import ( - "iter" - - "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/objectstore" - "github.com/beevik/etree" -) - -type DeviceInstanceSet objectstore.ObjectSet[*DeviceInstance] - -func (m *DeviceInstanceSet) Insert(obj *DeviceInstance) error { - return (*objectstore.ObjectSet[*DeviceInstance])(m).Insert(obj) -} - -func (m *DeviceInstanceSet) InsertOrReplace(obj *DeviceInstance) { - (*objectstore.ObjectSet[*DeviceInstance])(m).InsertOrReplace(obj) -} - -func (set *DeviceInstanceSet) Contains(obj *DeviceInstance) bool { - return (*objectstore.ObjectSet[*DeviceInstance])(set).Contains(obj) -} - -func (m *DeviceInstanceSet) All() iter.Seq[*DeviceInstance] { - return (*objectstore.ObjectSet[*DeviceInstance])(m).All() -} - -func (m *DeviceInstanceSet) ToXMLElement() *etree.Element { - elem := etree.NewElement("DeviceList") - - for sv := range m.All() { - elem.AddChild(sv.ToXMLElement()) - } - - return elem -} diff --git a/pmoupnp/device.go b/pmoupnp/device.go deleted file mode 100644 index 89f93ada..00000000 --- a/pmoupnp/device.go +++ /dev/null @@ -1,160 +0,0 @@ -package pmoupnp - -import ( - "fmt" -) - -type DeviceType string - -const ( - MediaServer DeviceType = "MediaServer" - MediaRenderer DeviceType = "MediaRenderer" -) - -type Device struct { - name string - devtype DeviceType - version int - - friendlyName string - manufacturer string - manufacturerURL string - modelDescription string - modelName string - modelNumber string - modelURL string - serialNumber string - specVersion string - - services ServiceSet -} - -// NewDevice creates a new UPnP Device with the given name and type. -// It populates a minimal set of device attributes such as -// FriendlyName, Manufacturer, ModelName and a default version. -// -// Parameters: -// -// name – the human‑readable name of the device. -// devtype – a unique string identifying the device type -// (used as the Device Identifier as well). -// -// Returns: -// -// *Device – a pointer to the freshly allocated Device instance. -// The caller owns the reference and may further -// customise the device by setting additional fields -// or services. -// -// Side effects: -// -// No I/O or external calls are performed. The function -// simply constructs a struct in memory; it is safe to -// call from multiple goroutines. -// -// Example: -// -// // Create a speaker device and register it with a server. -// dev := upnp.NewDevice("LivingRoomSpeaker", "AudioDevice") -// server.RegisterDevice(dev.Name(), dev) -func NewDevice(name string, devtype DeviceType) *Device { - switch devtype { - case MediaServer, MediaRenderer: - dev := &Device{ - name: name, - devtype: devtype, - friendlyName: "PMOMusic - " + name, - manufacturer: "Petit Maison Orange", - modelName: "PMOMusic - " + name, - version: 1, - services: make(ServiceSet), - } - return dev - default: - return nil - } - -} - -func (d *Device) Name() string { - return d.name -} - -func (d *Device) SetName(name string) { - d.name = name -} - -func (d *Device) SetFriendlyName(name string) { - d.friendlyName = name -} - -func (d *Device) SetModelName(name string) { - d.modelName = name -} - -func (d *Device) TypeID() string { - return "Device" -} - -func (d *Device) DeviceType() DeviceType { - return d.devtype -} - -func (d *Device) SetVersion(version int) error { - if version < 1 { - return fmt.Errorf("%s", "version must be greater than or equal to 1") - } - d.version = version - return nil -} - -func (d *Device) Version() int { - return d.version -} - -func (d *Device) Manufacturer() string { - return d.manufacturer -} - -func (d *Device) SetManufacturer(manufacturer string) { - d.manufacturer = manufacturer -} - -func (d *Device) ModelName() string { - return d.modelName -} - -func (d *Device) AddService(srv *Service) error { - err := d.services.Insert(srv) - - return err -} - -func (d *Device) NewInstance(server *Server, udn string) *DeviceInstance { - di := &DeviceInstance{ - name: d.name, - devtype: d.devtype, - version: d.version, - udn: udn, - server: server, - friendlyName: d.friendlyName, - manufacturer: d.manufacturer, - manufacturerURL: d.manufacturerURL, - modelDescription: d.modelDescription, - modelName: d.modelName, - modelNumber: d.modelNumber, - modelURL: d.modelURL, - serialNumber: d.serialNumber, - specVersion: d.specVersion, - devices: make(DeviceInstanceSet), // vide initialement - services: make(ServiceInstanceSet), - } - - for svc := range d.services.All() { - i := svc.NewInstance() - i.device = di - di.services.Insert(i) - } - - return di -} diff --git a/pmoupnp/deviceinstance.go b/pmoupnp/deviceinstance.go deleted file mode 100644 index e936ae62..00000000 --- a/pmoupnp/deviceinstance.go +++ /dev/null @@ -1,179 +0,0 @@ -package pmoupnp - -import ( - "fmt" - "net/http" - "runtime" - - "gargoton.petite-maison-orange.fr/eric/pmomusic/ssdp" - "github.com/beevik/etree" - log "github.com/sirupsen/logrus" -) - -type DeviceInstance struct { - // Identification spécifique à l’instance - name string - devtype DeviceType - version int - udn string - server *Server - - // Copie figée des infos du Device - friendlyName string - manufacturer string - manufacturerURL string - modelDescription string - modelName string - modelNumber string - modelURL string - serialNumber string - specVersion string - - // Sous-devices si le device en contient - devices DeviceInstanceSet - services ServiceInstanceSet -} - -func (di *DeviceInstance) Name() string { - return di.name -} - -func (di *DeviceInstance) TypeID() string { - return "DeviceInstance" -} - -func (di *DeviceInstance) DeviceType() DeviceType { - return di.devtype -} - -func (di *DeviceInstance) UDN() string { - return di.udn -} - -func (di *DeviceInstance) ServiceType() string { - return fmt.Sprintf("urn:schemas-upnp-org:device:%s:%d", di.devtype, di.version) -} - -func (di *DeviceInstance) FriendlyName() string { - return di.friendlyName -} - -func (di *DeviceInstance) Manufacturer() string { - return di.manufacturer -} - -func (di *DeviceInstance) ModelName() string { - return di.modelName -} - -func (di *DeviceInstance) BaseRoute() string { - return fmt.Sprintf("/device/%s/%s", di.DeviceType(), di.UDN()) -} -func (di *DeviceInstance) DescriptionURL() string { - return fmt.Sprintf("%s/desc.xml", di.BaseRoute()) -} - -func (di *DeviceInstance) RegisterURLs() error { - - mux, ok := di.server.httpSrv.Handler.(*http.ServeMux) - - if mux == nil || !ok { - return fmt.Errorf("❌ Device %s the server handler is not correctly defined", di.Name()) - } - - mux.HandleFunc( - di.DescriptionURL(), - di.server.ServeXML(di.ToXMLElement), - ) - - log.Infof( - "✅ Device description for %s available at : %s%s", - di.Name(), - di.server.BaseURL(), - di.DescriptionURL(), - ) - - for svc := range di.services.All() { - err := svc.RegisterURLs() - - if err != nil { - return fmt.Errorf( - "❌ Service %s:%s URL error: %v", - di.Name(), - svc.Name(), - err, - ) - } - } - - return nil -} - -func (di *DeviceInstance) NT() string { - return fmt.Sprintf("uuid:%s::urn:%s", di.UDN(), di.ServiceType()) -} - -func (di *DeviceInstance) RegisterSSPD() { - - osName := runtime.GOOS - arch := runtime.GOARCH - - dev := &ssdp.Device{ - UUID: di.UDN(), - DeviceType: di.ServiceType(), - Location: fmt.Sprintf("%s%s", di.server.BaseURL(), di.DescriptionURL()), - Server: fmt.Sprintf( - "%s/%s UPnP/1.1 PMOMusic/1.0", - osName, arch, - ), - NTs: make([]string, 0, 2+len(di.services)), - } - - dev.NTs = append( - dev.NTs, - "upnp:rootdevice", - di.ServiceType(), - ) - - for s := range di.services.All() { - dev.NTs = append(dev.NTs, s.ServiceType()) - } - - di.server.sspd.AddDevice(dev) -} - -func (di *DeviceInstance) UnregisterSSPD() { - di.server.sspd.RemoveDevice(di.UDN()) -} - -func (di *DeviceInstance) ToXMLElement() *etree.Element { - elem := etree.NewElement("root") - elem.CreateAttr("xmlns", "urn:schemas-upnp-org:device-1-0") - - spec := elem.CreateElement("specVersion") - spec.CreateElement("major").SetText("1") - spec.CreateElement("minor").SetText("0") - - device := elem.CreateElement("device") - device.CreateElement("deviceType").SetText(di.ServiceType()) - device.CreateElement("friendlyName").SetText(di.FriendlyName()) - device.CreateElement("manufacturer").SetText(di.Manufacturer()) - device.CreateElement("modelName").SetText(di.ModelName()) - device.CreateElement("UDN").SetText("uuid:" + di.UDN()) - - if len(di.services) > 0 { - device.AddChild(di.services.ToXMLElement()) - } - - return elem -} - -// // NewMediaRendererDescription génère la device description complète -// // comme *etree.Element (racine ). -// func NewMediaRendererDescription(udn string, friendlyName string) *etree.Element { - -// // Inject serviceList -// device.AddChild(NewMediaRendererServiceList(udn)) - -// return root -// } diff --git a/pmoupnp/devices/mediarenderer/AVTransport/ac_Play.go b/pmoupnp/devices/mediarenderer/AVTransport/ac_Play.go deleted file mode 100644 index f21ed3f2..00000000 --- a/pmoupnp/devices/mediarenderer/AVTransport/ac_Play.go +++ /dev/null @@ -1,23 +0,0 @@ -package avtransport - -import "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/services/actions" - -var Play = func() *actions.Action { - - ac := actions.NewAction("Play") - ac.AddArgument( - actions.NewInArgument( - "InstanceID", - A_ARG_TYPE_InstanceID, - ), - ) - - ac.AddArgument( - actions.NewInArgument( - "Speed", - TransportPlaySpeed, - ), - ) - - return ac -}() diff --git a/pmoupnp/devices/mediarenderer/AVTransport/ac_SetAVTransportURI.go b/pmoupnp/devices/mediarenderer/AVTransport/ac_SetAVTransportURI.go deleted file mode 100644 index 9095ad46..00000000 --- a/pmoupnp/devices/mediarenderer/AVTransport/ac_SetAVTransportURI.go +++ /dev/null @@ -1,30 +0,0 @@ -package avtransport - -import "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/services/actions" - -var SetAVTransportURI = func() *actions.Action { - - ac := actions.NewAction("SetAVTransportURI") - ac.AddArgument( - actions.NewInArgument( - "InstanceID", - A_ARG_TYPE_InstanceID, - ), - ) - - ac.AddArgument( - actions.NewInArgument( - "CurrentURI", - AVTransportURI, - ), - ) - - ac.AddArgument( - actions.NewInArgument( - "CurrentURIMetaData", - AVTransportURIMetaData, - ), - ) - - return ac -}() diff --git a/pmoupnp/devices/mediarenderer/AVTransport/ac_Stop.go b/pmoupnp/devices/mediarenderer/AVTransport/ac_Stop.go deleted file mode 100644 index 9543a9d0..00000000 --- a/pmoupnp/devices/mediarenderer/AVTransport/ac_Stop.go +++ /dev/null @@ -1,16 +0,0 @@ -package avtransport - -import "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/services/actions" - -var Stop = func() *actions.Action { - - ac := actions.NewAction("Stop") - ac.AddArgument( - actions.NewInArgument( - "InstanceID", - A_ARG_TYPE_InstanceID, - ), - ) - - return ac -}() diff --git a/pmoupnp/devices/mediarenderer/AVTransport/sv_AVTransportURI.go b/pmoupnp/devices/mediarenderer/AVTransport/sv_AVTransportURI.go deleted file mode 100644 index d92c3b02..00000000 --- a/pmoupnp/devices/mediarenderer/AVTransport/sv_AVTransportURI.go +++ /dev/null @@ -1,10 +0,0 @@ -package avtransport - -import sv "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/services/statevariables" - -var AVTransportURI = func() *sv.StateVariable { - - ts := sv.StateType_String.NewStateValue("AVTransportURI") - - return ts -}() diff --git a/pmoupnp/devices/mediarenderer/AVTransport/sv_AVTransportURIMetaData.go b/pmoupnp/devices/mediarenderer/AVTransport/sv_AVTransportURIMetaData.go deleted file mode 100644 index 258464c7..00000000 --- a/pmoupnp/devices/mediarenderer/AVTransport/sv_AVTransportURIMetaData.go +++ /dev/null @@ -1,25 +0,0 @@ -package avtransport - -import ( - "gargoton.petite-maison-orange.fr/eric/pmomusic/pmodidl" - sv "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/services/statevariables" - log "github.com/sirupsen/logrus" -) - -func _AVTransportURIMetaDataParser(value string) (interface{}, error) { - log.Debug("[avtransport] Parsing AVTransport)") - didl, err := pmodidl.Parse(value) - if err != nil { - return value, err - } - - return didl, nil -} - -var AVTransportURIMetaData = func() *sv.StateVariable { - - ts := sv.StateType_String.NewStateValue("AVTransportURIMetaData") - ts.SetValueParser(_AVTransportURIMetaDataParser) - - return ts -}() diff --git a/pmoupnp/devices/mediarenderer/AVTransport/sv_A_ARG_TYPE_InstanceID.go b/pmoupnp/devices/mediarenderer/AVTransport/sv_A_ARG_TYPE_InstanceID.go deleted file mode 100644 index 12351e4f..00000000 --- a/pmoupnp/devices/mediarenderer/AVTransport/sv_A_ARG_TYPE_InstanceID.go +++ /dev/null @@ -1,10 +0,0 @@ -package avtransport - -import sv "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/services/statevariables" - -var A_ARG_TYPE_InstanceID = func() *sv.StateVariable { - - ts := sv.StateType_UI4.NewStateValue("A_ARG_TYPE_InstanceID") - - return ts -}() diff --git a/pmoupnp/devices/mediarenderer/AVTransport/sv_A_ARG_TYPE_PlaySpeed.go b/pmoupnp/devices/mediarenderer/AVTransport/sv_A_ARG_TYPE_PlaySpeed.go deleted file mode 100644 index c78bfa14..00000000 --- a/pmoupnp/devices/mediarenderer/AVTransport/sv_A_ARG_TYPE_PlaySpeed.go +++ /dev/null @@ -1,10 +0,0 @@ -package avtransport - -import sv "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/services/statevariables" - -var A_ARG_TYPE_PlaySpeed = func() *sv.StateVariable { - - ts := sv.StateType_String.NewStateValue("A_ARG_TYPE_PlaySpeed") - - return ts -}() diff --git a/pmoupnp/devices/mediarenderer/AVTransport/sv_CurrentTrackDuration.go b/pmoupnp/devices/mediarenderer/AVTransport/sv_CurrentTrackDuration.go deleted file mode 100644 index 4f7be8e8..00000000 --- a/pmoupnp/devices/mediarenderer/AVTransport/sv_CurrentTrackDuration.go +++ /dev/null @@ -1,10 +0,0 @@ -package avtransport - -import sv "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/services/statevariables" - -var CurrentTrackDuration = func() *sv.StateVariable { - - ts := sv.StateType_String.NewStateValue("CurrentTrackDuration") - - return ts -}() diff --git a/pmoupnp/devices/mediarenderer/AVTransport/sv_SeekMode.go b/pmoupnp/devices/mediarenderer/AVTransport/sv_SeekMode.go deleted file mode 100644 index c3587d0c..00000000 --- a/pmoupnp/devices/mediarenderer/AVTransport/sv_SeekMode.go +++ /dev/null @@ -1,10 +0,0 @@ -package avtransport - -import sv "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/services/statevariables" - -var SeekMode = func() *sv.StateVariable { - - ts := sv.StateType_String.NewStateValue("SeekMode") - - return ts -}() diff --git a/pmoupnp/devices/mediarenderer/AVTransport/sv_TransportPlaySpeed.go b/pmoupnp/devices/mediarenderer/AVTransport/sv_TransportPlaySpeed.go deleted file mode 100644 index 4d92d0ba..00000000 --- a/pmoupnp/devices/mediarenderer/AVTransport/sv_TransportPlaySpeed.go +++ /dev/null @@ -1,11 +0,0 @@ -package avtransport - -import sv "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/services/statevariables" - -var TransportPlaySpeed = func() *sv.StateVariable { - - ts := sv.StateType_String.NewStateValue("TransportPlaySpeed") - ts.AppendAllowedValue("1") - - return ts -}() diff --git a/pmoupnp/devices/mediarenderer/AVTransport/sv_TransportState.go b/pmoupnp/devices/mediarenderer/AVTransport/sv_TransportState.go deleted file mode 100644 index a546bdf9..00000000 --- a/pmoupnp/devices/mediarenderer/AVTransport/sv_TransportState.go +++ /dev/null @@ -1,22 +0,0 @@ -package avtransport - -import sv "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/services/statevariables" - -var TransportState = func() *sv.StateVariable { - - ts := sv.StateType_String.NewStateValue("TransportState") - - ts.SetAllowedValues( - "STOPPED", - "PLAYING", - "RECORDING", - "TRANSITIONING", - "PAUSED_PLAYBACK", - "PAUSED_RECORDING", - "NO_MEDIA_PRESENT", - ) - - ts.SetSendingEvents() - - return ts -}() diff --git a/pmoupnp/devices/mediarenderer/AVTransport/sv_TransportStatus.go b/pmoupnp/devices/mediarenderer/AVTransport/sv_TransportStatus.go deleted file mode 100644 index fe87fb04..00000000 --- a/pmoupnp/devices/mediarenderer/AVTransport/sv_TransportStatus.go +++ /dev/null @@ -1,17 +0,0 @@ -package avtransport - -import sv "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/services/statevariables" - -var TransportStatus = func() *sv.StateVariable { - - ts := sv.StateType_String.NewStateValue("TransportStatus") - - ts.SetAllowedValues( - "OK", - "ERROR_OCCURRED", - ) - - ts.SetSendingEvents() - - return ts -}() diff --git a/pmoupnp/devices/mediarenderer/AVTransport/svc_avtransport.go b/pmoupnp/devices/mediarenderer/AVTransport/svc_avtransport.go deleted file mode 100644 index 27ec7547..00000000 --- a/pmoupnp/devices/mediarenderer/AVTransport/svc_avtransport.go +++ /dev/null @@ -1,23 +0,0 @@ -package avtransport - -import "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp" - -var AVTransport = func() *pmoupnp.Service { - svc := pmoupnp.NewService("AVTransport") - - svc.AddAction(SetAVTransportURI) - svc.AddAction(Play) - svc.AddAction(Stop) - - svc.AddVariable(A_ARG_TYPE_InstanceID) - svc.AddVariable(A_ARG_TYPE_PlaySpeed) - svc.AddVariable(AVTransportURI) - svc.AddVariable(AVTransportURIMetaData) - svc.AddVariable(CurrentTrackDuration) - svc.AddVariable(SeekMode) - svc.AddVariable(TransportPlaySpeed) - svc.AddVariable(TransportState) - svc.AddVariable(TransportStatus) - - return svc -}() diff --git a/pmoupnp/devices/mediarenderer/ConnectionManager/ac_GetCurrentConnectionIDs.go b/pmoupnp/devices/mediarenderer/ConnectionManager/ac_GetCurrentConnectionIDs.go deleted file mode 100644 index 2b11f56d..00000000 --- a/pmoupnp/devices/mediarenderer/ConnectionManager/ac_GetCurrentConnectionIDs.go +++ /dev/null @@ -1,16 +0,0 @@ -package connectionmanager - -import "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/services/actions" - -var GetCurrentConnectionIDs = func() *actions.Action { - - ac := actions.NewAction("GetCurrentConnectionIDs") - ac.AddArgument( - actions.NewOutArgument( - "ConnectionIDs", - CurrentConnectionIDs, - ), - ) - - return ac -}() diff --git a/pmoupnp/devices/mediarenderer/ConnectionManager/ac_GetCurrentConnectionInfo.go b/pmoupnp/devices/mediarenderer/ConnectionManager/ac_GetCurrentConnectionInfo.go deleted file mode 100644 index 5a1057ea..00000000 --- a/pmoupnp/devices/mediarenderer/ConnectionManager/ac_GetCurrentConnectionInfo.go +++ /dev/null @@ -1,64 +0,0 @@ -package connectionmanager - -import "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/services/actions" - -var GetCurrentConnectionInfo = func() *actions.Action { - - ac := actions.NewAction("GetCurrentConnectionInfo") - ac.AddArgument( - actions.NewInArgument( - "ConnectionIDs", - A_ARG_TYPE_ConnectionID, - ), - ) - - ac.AddArgument( - actions.NewOutArgument( - "RcsID", - A_ARG_TYPE_RcsID, - ), - ) - - ac.AddArgument( - actions.NewOutArgument( - "AVTransportID", - A_ARG_TYPE_AVTransportID, - ), - ) - - ac.AddArgument( - actions.NewOutArgument( - "ProtocolInfo", - A_ARG_TYPE_ProtocolInfo, - ), - ) - - ac.AddArgument( - actions.NewOutArgument( - "PeerConnectionManager", - A_ARG_TYPE_ConnectionManager, - ), - ) - - ac.AddArgument( - actions.NewOutArgument( - "PeerConnectionID", - A_ARG_TYPE_ConnectionID, - ), - ) - - ac.AddArgument( - actions.NewOutArgument( - "Direction", - A_ARG_TYPE_Direction, - ), - ) - - ac.AddArgument( - actions.NewOutArgument( - "Status", - A_ARG_TYPE_ConnectionStatus, - ), - ) - return ac -}() diff --git a/pmoupnp/devices/mediarenderer/ConnectionManager/ac_GetProtocolInfo.go b/pmoupnp/devices/mediarenderer/ConnectionManager/ac_GetProtocolInfo.go deleted file mode 100644 index d1f63531..00000000 --- a/pmoupnp/devices/mediarenderer/ConnectionManager/ac_GetProtocolInfo.go +++ /dev/null @@ -1,23 +0,0 @@ -package connectionmanager - -import "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/services/actions" - -var GetProtocolInfo = func() *actions.Action { - - ac := actions.NewAction("GetProtocolInfo") - ac.AddArgument( - actions.NewOutArgument( - "Source", - SourceProtocolInfo, - ), - ) - - ac.AddArgument( - actions.NewOutArgument( - "Sink", - SinkProtocolInfo, - ), - ) - - return ac -}() diff --git a/pmoupnp/devices/mediarenderer/ConnectionManager/sv_AVTransportID.go b/pmoupnp/devices/mediarenderer/ConnectionManager/sv_AVTransportID.go deleted file mode 100644 index 0894aed5..00000000 --- a/pmoupnp/devices/mediarenderer/ConnectionManager/sv_AVTransportID.go +++ /dev/null @@ -1,10 +0,0 @@ -package connectionmanager - -import sv "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/services/statevariables" - -var AVTransportID = func() *sv.StateVariable { - - ts := sv.StateType_I4.NewStateValue("AVTransportID") - - return ts -}() diff --git a/pmoupnp/devices/mediarenderer/ConnectionManager/sv_A_ARG_TYPE_AVTransportID.go b/pmoupnp/devices/mediarenderer/ConnectionManager/sv_A_ARG_TYPE_AVTransportID.go deleted file mode 100644 index 375d8c5e..00000000 --- a/pmoupnp/devices/mediarenderer/ConnectionManager/sv_A_ARG_TYPE_AVTransportID.go +++ /dev/null @@ -1,10 +0,0 @@ -package connectionmanager - -import sv "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/services/statevariables" - -var A_ARG_TYPE_AVTransportID = func() *sv.StateVariable { - - ts := sv.StateType_I4.NewStateValue("A_ARG_TYPE_AVTransportID") - - return ts -}() diff --git a/pmoupnp/devices/mediarenderer/ConnectionManager/sv_A_ARG_TYPE_ConnectionID.go b/pmoupnp/devices/mediarenderer/ConnectionManager/sv_A_ARG_TYPE_ConnectionID.go deleted file mode 100644 index dc289754..00000000 --- a/pmoupnp/devices/mediarenderer/ConnectionManager/sv_A_ARG_TYPE_ConnectionID.go +++ /dev/null @@ -1,10 +0,0 @@ -package connectionmanager - -import sv "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/services/statevariables" - -var A_ARG_TYPE_ConnectionID = func() *sv.StateVariable { - - ts := sv.StateType_I4.NewStateValue("A_ARG_TYPE_ConnectionID") - - return ts -}() diff --git a/pmoupnp/devices/mediarenderer/ConnectionManager/sv_A_ARG_TYPE_ConnectionManager.go b/pmoupnp/devices/mediarenderer/ConnectionManager/sv_A_ARG_TYPE_ConnectionManager.go deleted file mode 100644 index 73a30f33..00000000 --- a/pmoupnp/devices/mediarenderer/ConnectionManager/sv_A_ARG_TYPE_ConnectionManager.go +++ /dev/null @@ -1,10 +0,0 @@ -package connectionmanager - -import sv "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/services/statevariables" - -var A_ARG_TYPE_ConnectionManager = func() *sv.StateVariable { - - ts := sv.StateType_String.NewStateValue("A_ARG_TYPE_ConnectionManager") - - return ts -}() diff --git a/pmoupnp/devices/mediarenderer/ConnectionManager/sv_A_ARG_TYPE_ConnectionStatus.go b/pmoupnp/devices/mediarenderer/ConnectionManager/sv_A_ARG_TYPE_ConnectionStatus.go deleted file mode 100644 index 973761ff..00000000 --- a/pmoupnp/devices/mediarenderer/ConnectionManager/sv_A_ARG_TYPE_ConnectionStatus.go +++ /dev/null @@ -1,17 +0,0 @@ -package connectionmanager - -import sv "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/services/statevariables" - -var A_ARG_TYPE_ConnectionStatus = func() *sv.StateVariable { - - ts := sv.StateType_String.NewStateValue("A_ARG_TYPE_ConnectionStatus") - - ts.AppendAllowedValue( - "OK", - "ContentFormatMismatch", - "InsufficientBandwidth", - "UnreliableChannel", - "Unknown", - ) - return ts -}() diff --git a/pmoupnp/devices/mediarenderer/ConnectionManager/sv_A_ARG_TYPE_Direction.go b/pmoupnp/devices/mediarenderer/ConnectionManager/sv_A_ARG_TYPE_Direction.go deleted file mode 100644 index ed912541..00000000 --- a/pmoupnp/devices/mediarenderer/ConnectionManager/sv_A_ARG_TYPE_Direction.go +++ /dev/null @@ -1,11 +0,0 @@ -package connectionmanager - -import sv "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/services/statevariables" - -var A_ARG_TYPE_Direction = func() *sv.StateVariable { - - ts := sv.StateType_String.NewStateValue("A_ARG_TYPE_Direction") - ts.AppendAllowedValue("Input", "Output") - - return ts -}() diff --git a/pmoupnp/devices/mediarenderer/ConnectionManager/sv_A_ARG_TYPE_ProtocolInfo.go b/pmoupnp/devices/mediarenderer/ConnectionManager/sv_A_ARG_TYPE_ProtocolInfo.go deleted file mode 100644 index 228b4824..00000000 --- a/pmoupnp/devices/mediarenderer/ConnectionManager/sv_A_ARG_TYPE_ProtocolInfo.go +++ /dev/null @@ -1,10 +0,0 @@ -package connectionmanager - -import sv "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/services/statevariables" - -var A_ARG_TYPE_ProtocolInfo = func() *sv.StateVariable { - - ts := sv.StateType_String.NewStateValue("A_ARG_TYPE_ProtocolInfo") - - return ts -}() diff --git a/pmoupnp/devices/mediarenderer/ConnectionManager/sv_A_ARG_TYPE_RcsID.go b/pmoupnp/devices/mediarenderer/ConnectionManager/sv_A_ARG_TYPE_RcsID.go deleted file mode 100644 index bb5f1642..00000000 --- a/pmoupnp/devices/mediarenderer/ConnectionManager/sv_A_ARG_TYPE_RcsID.go +++ /dev/null @@ -1,10 +0,0 @@ -package connectionmanager - -import sv "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/services/statevariables" - -var A_ARG_TYPE_RcsID = func() *sv.StateVariable { - - ts := sv.StateType_I4.NewStateValue("A_ARG_TYPE_RcsID") - - return ts -}() diff --git a/pmoupnp/devices/mediarenderer/ConnectionManager/sv_ConnectionID.go b/pmoupnp/devices/mediarenderer/ConnectionManager/sv_ConnectionID.go deleted file mode 100644 index bd6e6d4b..00000000 --- a/pmoupnp/devices/mediarenderer/ConnectionManager/sv_ConnectionID.go +++ /dev/null @@ -1,10 +0,0 @@ -package connectionmanager - -import sv "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/services/statevariables" - -var ConnectionID = func() *sv.StateVariable { - - ts := sv.StateType_I4.NewStateValue("ConnectionID") - - return ts -}() diff --git a/pmoupnp/devices/mediarenderer/ConnectionManager/sv_CurrentConnectionIDs.go b/pmoupnp/devices/mediarenderer/ConnectionManager/sv_CurrentConnectionIDs.go deleted file mode 100644 index aa4b60be..00000000 --- a/pmoupnp/devices/mediarenderer/ConnectionManager/sv_CurrentConnectionIDs.go +++ /dev/null @@ -1,10 +0,0 @@ -package connectionmanager - -import sv "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/services/statevariables" - -var CurrentConnectionIDs = func() *sv.StateVariable { - - ts := sv.StateType_String.NewStateValue("CurrentConnectionIDs") - - return ts -}() diff --git a/pmoupnp/devices/mediarenderer/ConnectionManager/sv_Direction.go b/pmoupnp/devices/mediarenderer/ConnectionManager/sv_Direction.go deleted file mode 100644 index 9766fe63..00000000 --- a/pmoupnp/devices/mediarenderer/ConnectionManager/sv_Direction.go +++ /dev/null @@ -1,11 +0,0 @@ -package connectionmanager - -import sv "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/services/statevariables" - -var Direction = func() *sv.StateVariable { - - ts := sv.StateType_String.NewStateValue("Direction") - ts.AppendAllowedValue("Input", "Ouput") - - return ts -}() diff --git a/pmoupnp/devices/mediarenderer/ConnectionManager/sv_PeerConnectionID.go b/pmoupnp/devices/mediarenderer/ConnectionManager/sv_PeerConnectionID.go deleted file mode 100644 index 44bfd94f..00000000 --- a/pmoupnp/devices/mediarenderer/ConnectionManager/sv_PeerConnectionID.go +++ /dev/null @@ -1,10 +0,0 @@ -package connectionmanager - -import sv "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/services/statevariables" - -var PeerConnectionID = func() *sv.StateVariable { - - ts := sv.StateType_I4.NewStateValue("PeerConnectionID") - - return ts -}() diff --git a/pmoupnp/devices/mediarenderer/ConnectionManager/sv_PeerConnectionManager.go b/pmoupnp/devices/mediarenderer/ConnectionManager/sv_PeerConnectionManager.go deleted file mode 100644 index 69ac0d39..00000000 --- a/pmoupnp/devices/mediarenderer/ConnectionManager/sv_PeerConnectionManager.go +++ /dev/null @@ -1,10 +0,0 @@ -package connectionmanager - -import sv "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/services/statevariables" - -var PeerConnectionManager = func() *sv.StateVariable { - - ts := sv.StateType_String.NewStateValue("PeerConnectionManager") - - return ts -}() diff --git a/pmoupnp/devices/mediarenderer/ConnectionManager/sv_RcsID.go b/pmoupnp/devices/mediarenderer/ConnectionManager/sv_RcsID.go deleted file mode 100644 index a28e177c..00000000 --- a/pmoupnp/devices/mediarenderer/ConnectionManager/sv_RcsID.go +++ /dev/null @@ -1,10 +0,0 @@ -package connectionmanager - -import sv "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/services/statevariables" - -var RcsID = func() *sv.StateVariable { - - ts := sv.StateType_I4.NewStateValue("RcsID") - - return ts -}() diff --git a/pmoupnp/devices/mediarenderer/ConnectionManager/sv_SinkProtocolInfo.go b/pmoupnp/devices/mediarenderer/ConnectionManager/sv_SinkProtocolInfo.go deleted file mode 100644 index 8283af8f..00000000 --- a/pmoupnp/devices/mediarenderer/ConnectionManager/sv_SinkProtocolInfo.go +++ /dev/null @@ -1,10 +0,0 @@ -package connectionmanager - -import sv "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/services/statevariables" - -var SinkProtocolInfo = func() *sv.StateVariable { - - ts := sv.StateType_String.NewStateValue("SinkProtocolInfo") - - return ts -}() diff --git a/pmoupnp/devices/mediarenderer/ConnectionManager/sv_SourceProtocolInfo.go b/pmoupnp/devices/mediarenderer/ConnectionManager/sv_SourceProtocolInfo.go deleted file mode 100644 index 8df32697..00000000 --- a/pmoupnp/devices/mediarenderer/ConnectionManager/sv_SourceProtocolInfo.go +++ /dev/null @@ -1,10 +0,0 @@ -package connectionmanager - -import sv "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/services/statevariables" - -var SourceProtocolInfo = func() *sv.StateVariable { - - ts := sv.StateType_String.NewStateValue("SourceProtocolInfo") - - return ts -}() diff --git a/pmoupnp/devices/mediarenderer/ConnectionManager/sv_Status.go b/pmoupnp/devices/mediarenderer/ConnectionManager/sv_Status.go deleted file mode 100644 index 7c92d3ec..00000000 --- a/pmoupnp/devices/mediarenderer/ConnectionManager/sv_Status.go +++ /dev/null @@ -1,17 +0,0 @@ -package connectionmanager - -import sv "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/services/statevariables" - -var Status = func() *sv.StateVariable { - - ts := sv.StateType_String.NewStateValue("Status") - ts.AppendAllowedValue( - "OK", - "ContentFormatMismatch", - "InsufficientBandwidth", - "UnreliableChannel", - "Unknown", - ) - - return ts -}() diff --git a/pmoupnp/devices/mediarenderer/ConnectionManager/svc_connectionmanager.go b/pmoupnp/devices/mediarenderer/ConnectionManager/svc_connectionmanager.go deleted file mode 100644 index c9e1b03b..00000000 --- a/pmoupnp/devices/mediarenderer/ConnectionManager/svc_connectionmanager.go +++ /dev/null @@ -1,32 +0,0 @@ -package connectionmanager - -import "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp" - -var ConnectionManager = func() *pmoupnp.Service { - svc := pmoupnp.NewService("ConnectionManager") - - svc.AddVariable(AVTransportID) - svc.AddVariable(ConnectionID) - svc.AddVariable(CurrentConnectionIDs) - svc.AddVariable(Direction) - svc.AddVariable(PeerConnectionID) - svc.AddVariable(PeerConnectionManager) - svc.AddVariable(RcsID) - svc.AddVariable(SinkProtocolInfo) - svc.AddVariable(SourceProtocolInfo) - svc.AddVariable(Status) - - svc.AddVariable(A_ARG_TYPE_AVTransportID) - svc.AddVariable(A_ARG_TYPE_ConnectionID) - svc.AddVariable(A_ARG_TYPE_ConnectionManager) - svc.AddVariable(A_ARG_TYPE_ConnectionStatus) - svc.AddVariable(A_ARG_TYPE_Direction) - svc.AddVariable(A_ARG_TYPE_ProtocolInfo) - svc.AddVariable(A_ARG_TYPE_RcsID) - - svc.AddAction(GetCurrentConnectionIDs) - svc.AddAction(GetCurrentConnectionInfo) - svc.AddAction(GetProtocolInfo) - - return svc -}() diff --git a/pmoupnp/devices/mediarenderer/RenderingControl/sv_Channel.go b/pmoupnp/devices/mediarenderer/RenderingControl/sv_Channel.go deleted file mode 100644 index ac17719a..00000000 --- a/pmoupnp/devices/mediarenderer/RenderingControl/sv_Channel.go +++ /dev/null @@ -1,11 +0,0 @@ -package renderingcontrol - -import sv "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/services/statevariables" - -var Channel = func() *sv.StateVariable { - - ts := sv.StateType_String.NewStateValue("Channel") - ts.AppendAllowedValue("Master", "LF", "RF") - - return ts -}() diff --git a/pmoupnp/devices/mediarenderer/RenderingControl/sv_InstanceID.go b/pmoupnp/devices/mediarenderer/RenderingControl/sv_InstanceID.go deleted file mode 100644 index ce964a5d..00000000 --- a/pmoupnp/devices/mediarenderer/RenderingControl/sv_InstanceID.go +++ /dev/null @@ -1,10 +0,0 @@ -package renderingcontrol - -import sv "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/services/statevariables" - -var InstanceID = func() *sv.StateVariable { - - ts := sv.StateType_I4.NewStateValue("InstanceID") - - return ts -}() diff --git a/pmoupnp/devices/mediarenderer/RenderingControl/sv_Mute.go b/pmoupnp/devices/mediarenderer/RenderingControl/sv_Mute.go deleted file mode 100644 index e441095f..00000000 --- a/pmoupnp/devices/mediarenderer/RenderingControl/sv_Mute.go +++ /dev/null @@ -1,12 +0,0 @@ -package renderingcontrol - -import sv "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/services/statevariables" - -var Mute = func() *sv.StateVariable { - - ts := sv.StateType_Boolean.NewStateValue("Mute") - ts.SetSendingEvents() - ts.SetDefault(false) - - return ts -}() diff --git a/pmoupnp/devices/mediarenderer/RenderingControl/sv_SourceProtocolInfo.go b/pmoupnp/devices/mediarenderer/RenderingControl/sv_SourceProtocolInfo.go deleted file mode 100644 index 498839a2..00000000 --- a/pmoupnp/devices/mediarenderer/RenderingControl/sv_SourceProtocolInfo.go +++ /dev/null @@ -1 +0,0 @@ -package renderingcontrol diff --git a/pmoupnp/devices/mediarenderer/RenderingControl/sv_Volume.go b/pmoupnp/devices/mediarenderer/RenderingControl/sv_Volume.go deleted file mode 100644 index 487c3133..00000000 --- a/pmoupnp/devices/mediarenderer/RenderingControl/sv_Volume.go +++ /dev/null @@ -1,15 +0,0 @@ -package renderingcontrol - -import sv "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/services/statevariables" - -var Volume = func() *sv.StateVariable { - - vol := sv.StateType_UI2.NewStateValue("Volume") - - vol.SetRange(0, 100) - vol.SetStep(1) - - vol.SetSendingEvents() - - return vol -}() diff --git a/pmoupnp/devices/mediarenderer/RenderingControl/svc_renderingcontrol.go b/pmoupnp/devices/mediarenderer/RenderingControl/svc_renderingcontrol.go deleted file mode 100644 index 1fe6e123..00000000 --- a/pmoupnp/devices/mediarenderer/RenderingControl/svc_renderingcontrol.go +++ /dev/null @@ -1,14 +0,0 @@ -package renderingcontrol - -import "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp" - -var RenderingControl = func() *pmoupnp.Service { - svc := pmoupnp.NewService("RenderingControl") - - svc.AddVariable(InstanceID) - svc.AddVariable(Channel) - svc.AddVariable(Mute) - svc.AddVariable(Volume) - - return svc -}() diff --git a/pmoupnp/devices/mediarenderer/mr_fake_renderer.go b/pmoupnp/devices/mediarenderer/mr_fake_renderer.go deleted file mode 100644 index b61c8f52..00000000 --- a/pmoupnp/devices/mediarenderer/mr_fake_renderer.go +++ /dev/null @@ -1,18 +0,0 @@ -package mediarenderer - -import ( - "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp" - avtransport "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/mediarenderer/AVTransport" - connectionmanager "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/mediarenderer/ConnectionManager" - renderingcontrol "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/mediarenderer/RenderingControl" -) - -var FakeRenderer = func() *pmoupnp.Device { - - renderer := pmoupnp.NewDevice("FakeRenderer", "MediaRenderer") - - renderer.AddService(avtransport.AVTransport) - renderer.AddService(connectionmanager.ConnectionManager) - renderer.AddService(renderingcontrol.RenderingControl) - return renderer -}() diff --git a/pmoupnp/devices/services/actions/action.go b/pmoupnp/devices/services/actions/action.go deleted file mode 100644 index 067bf423..00000000 --- a/pmoupnp/devices/services/actions/action.go +++ /dev/null @@ -1,37 +0,0 @@ -package actions - -import "maps" - -type Action struct { - name string - arguments ArgumentSet -} - -func NewAction(name string) *Action { - ac := &Action{ - name: name, - arguments: make(ArgumentSet), - } - - return ac -} - -func (a *Action) Name() string { - return a.name -} - -func (a *Action) TypeID() string { - return "Action" -} - -func (a *Action) AddArgument(arg *Argument) { - a.arguments.Insert(arg) -} - -func (a *Action) NewInstance() *ActionInstance { - ac := &ActionInstance{ - model: a, - arguments: maps.Clone(a.arguments), - } - return ac -} diff --git a/pmoupnp/devices/services/actions/actioninstance.go b/pmoupnp/devices/services/actions/actioninstance.go deleted file mode 100644 index c5b548f0..00000000 --- a/pmoupnp/devices/services/actions/actioninstance.go +++ /dev/null @@ -1,32 +0,0 @@ -package actions - -import "github.com/beevik/etree" - -type ActionInstance struct { - model *Action - - arguments ArgumentSet -} - -func (a *ActionInstance) Name() string { - return a.model.Name() -} - -func (a *ActionInstance) TypeID() string { - return "ActionInstance" -} - -func (a *ActionInstance) Arguments(name string) (*Argument, bool) { - arg, ok := a.arguments[name] - return arg, ok -} - -func (a *ActionInstance) ToXMLElement() *etree.Element { - elem := etree.NewElement("action") - - name := elem.CreateElement("name") - name.SetText(a.Name()) - - elem.AddChild(a.arguments.ToXMLElement()) - return elem -} diff --git a/pmoupnp/devices/services/actions/actioninstanceset.go b/pmoupnp/devices/services/actions/actioninstanceset.go deleted file mode 100644 index bada65a3..00000000 --- a/pmoupnp/devices/services/actions/actioninstanceset.go +++ /dev/null @@ -1,32 +0,0 @@ -package actions - -import ( - "iter" - - "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/objectstore" - "github.com/beevik/etree" -) - -type ActionInstanceSet objectstore.ObjectSet[*ActionInstance] - -func (m *ActionInstanceSet) Insert(obj *ActionInstance) { - (*objectstore.ObjectSet[*ActionInstance])(m).Insert(obj) -} - -func (set *ActionInstanceSet) Contains(obj *ActionInstance) bool { - return (*objectstore.ObjectSet[*ActionInstance])(set).Contains(obj) -} - -func (m *ActionInstanceSet) All() iter.Seq[*ActionInstance] { - return (*objectstore.ObjectSet[*ActionInstance])(m).All() -} - -func (m *ActionInstanceSet) ToXMLElement() *etree.Element { - elem := etree.NewElement("actionList") - - for sv := range m.All() { - elem.AddChild(sv.ToXMLElement()) - } - - return elem -} diff --git a/pmoupnp/devices/services/actions/actionset.go b/pmoupnp/devices/services/actions/actionset.go deleted file mode 100644 index f076e271..00000000 --- a/pmoupnp/devices/services/actions/actionset.go +++ /dev/null @@ -1,25 +0,0 @@ -package actions - -import ( - "iter" - - "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/objectstore" -) - -type ActionSet objectstore.ObjectSet[*Action] - -func (m *ActionSet) Insert(obj *Action) error { - return (*objectstore.ObjectSet[*Action])(m).Insert(obj) -} - -func (m *ActionSet) InsertOrReplace(obj *Action) { - (*objectstore.ObjectSet[*Action])(m).InsertOrReplace(obj) -} - -func (set *ActionSet) Contains(obj *Action) bool { - return (*objectstore.ObjectSet[*Action])(set).Contains(obj) -} - -func (m *ActionSet) All() iter.Seq[*Action] { - return (*objectstore.ObjectSet[*Action])(m).All() -} diff --git a/pmoupnp/devices/services/actions/argument.go b/pmoupnp/devices/services/actions/argument.go deleted file mode 100644 index 5827047c..00000000 --- a/pmoupnp/devices/services/actions/argument.go +++ /dev/null @@ -1,100 +0,0 @@ -package actions - -import ( - "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/services/statevariables" - "github.com/beevik/etree" -) - -type Argument struct { - name string - statevariables *statevariables.StateVariable - in bool - out bool -} - -func newArgument(name string, statevariable *statevariables.StateVariable) *Argument { - arg := &Argument{ - name: name, - statevariables: statevariable, - } - return arg -} - -func NewInArgument(name string, statevariable *statevariables.StateVariable) *Argument { - arg := newArgument(name, statevariable) - arg.in = true - return arg -} - -func NewOutArgument(name string, statevariable *statevariables.StateVariable) *Argument { - arg := newArgument(name, statevariable) - arg.out = true - return arg -} - -func NewInOutArgument(name string, statevariable *statevariables.StateVariable) *Argument { - arg := newArgument(name, statevariable) - arg.in = true - arg.out = true - return arg -} - -func (a *Argument) Name() string { - return a.name -} - -func (sv Argument) TypeID() string { - return "Argument" -} - -func (a *Argument) StateVariable() *statevariables.StateVariable { - return a.statevariables -} - -func (a *Argument) IsIn() bool { - return a.in -} - -func (a *Argument) IsOut() bool { - return a.out -} - -func (a *Argument) ToXMLElement() *etree.Element { - var elem, arg *etree.Element - - if a.IsIn() && a.IsOut() { - elem = etree.NewElement("") - arg = elem.CreateElement("argument") - } else { - elem = etree.NewElement("argument") - arg = elem - } - - if a.IsIn() { - name := arg.CreateElement("name") - name.SetText(a.Name()) - - direction := arg.CreateElement("direction") - direction.SetText("in") - - relatedStateVariable := arg.CreateElement("relatedStateVariable") - relatedStateVariable.SetText(a.StateVariable().Name()) - } - - if a.IsIn() && a.IsOut() { - arg = elem.CreateElement("argument") - } - - if a.IsOut() { - name := arg.CreateElement("name") - name.SetText(a.Name()) - - direction := arg.CreateElement("direction") - direction.SetText("out") - - relatedStateVariable := arg.CreateElement("relatedStateVariable") - relatedStateVariable.SetText(a.StateVariable().Name()) - } - - return elem -} diff --git a/pmoupnp/devices/services/actions/argumentset.go b/pmoupnp/devices/services/actions/argumentset.go deleted file mode 100644 index 45efed73..00000000 --- a/pmoupnp/devices/services/actions/argumentset.go +++ /dev/null @@ -1,32 +0,0 @@ -package actions - -import ( - "iter" - - "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/objectstore" - "github.com/beevik/etree" -) - -type ArgumentSet objectstore.ObjectSet[*Argument] - -func (m *ArgumentSet) Insert(obj *Argument) { - (*objectstore.ObjectSet[*Argument])(m).Insert(obj) -} - -func (set *ArgumentSet) Contains(obj *Argument) bool { - return (*objectstore.ObjectSet[*Argument])(set).Contains(obj) -} - -func (m *ArgumentSet) All() iter.Seq[*Argument] { - return (*objectstore.ObjectSet[*Argument])(m).All() -} - -func (m *ArgumentSet) ToXMLElement() *etree.Element { - elem := etree.NewElement("argumentList") - - for sv := range m.All() { - elem.AddChild(sv.ToXMLElement()) - } - - return elem -} diff --git a/pmoupnp/devices/services/statevariables/statevalueinstance.go b/pmoupnp/devices/services/statevariables/statevalueinstance.go deleted file mode 100644 index 2b465211..00000000 --- a/pmoupnp/devices/services/statevariables/statevalueinstance.go +++ /dev/null @@ -1,402 +0,0 @@ -package statevariables - -import ( - "encoding/base64" - "encoding/hex" - "errors" - "fmt" - "net/url" - "reflect" - "sync" - "time" - - "github.com/beevik/etree" - "github.com/google/uuid" - log "github.com/sirupsen/logrus" -) - -type notifiable interface { - Name() string - EventToBeSent(name string, value interface{}) -} - -type StateVarInstance struct { - model *StateVariable - name string - modifiable bool - description string - step interface{} // Step size for incremental state values (e.g., "10") - defaultValue interface{} - valueRange *ValueRange - eventConditions map[string]StateConditionFunc - allowedValues []interface{} - sendEvents bool - parse StringValueParser - marshal ValueSerializer - service notifiable - value interface{} - previousValue interface{} - lastChange time.Time - lastEvent time.Time - mu sync.RWMutex -} - -func (instance *StateVarInstance) Name() string { - return instance.model.Name() -} - -func (sv *StateVarInstance) TypeID() string { - return "StateVarInstance" -} - -func (instance *StateVarInstance) BitSize() int { - return instance.model.BitSize() -} - -func (instance *StateVarInstance) Cast(val interface{}) (interface{}, error) { - return instance.model.Cast(val) -} - -func (instance *StateVarInstance) HasDefault() bool { - return instance.defaultValue != nil -} - -func (instance *StateVarInstance) DefaultValue() interface{} { - return instance.defaultValue -} - -func (instance *StateVarInstance) HasRange() bool { - return instance.valueRange != nil -} - -func (instance *StateVarInstance) Minimum() interface{} { - if instance.valueRange == nil { - return nil - } - return instance.valueRange.min -} - -func (instance *StateVarInstance) Maximum() interface{} { - if instance.valueRange == nil { - return nil - } - return instance.valueRange.max -} - -func (instance *StateVarInstance) IsSendingEvents() bool { - return instance.sendEvents -} - -func (instance *StateVarInstance) HasAllowedValues() bool { - return len(instance.allowedValues) > 0 -} - -func (instance *StateVarInstance) AllowedValues() []interface{} { - return instance.allowedValues -} - -func (instance *StateVarInstance) HasParser() bool { - return instance.parse != nil -} - -func (instance *StateVarInstance) ParseValue(value string) (interface{}, error) { - if instance.parse == nil { - return value, errors.New("Not parsed value") - } - return instance.parse(value) -} - -// IsValueInRange checks if a value falls within the defined range. -// Always returns true if no range is set. -// Parameters: -// -// value: Value to check -// -// Returns: -// bool: True if within range or no range defined -func (instance *StateVarInstance) IsValueInRange(value interface{}) (bool, error) { - return instance.model.valueType.InRange(value, instance.valueRange) -} - -func (instance *StateVarInstance) IsValueAllowed(value interface{}) (bool, error) { - if !instance.HasAllowedValues() { - return true, nil // No list = any value valid - } - cvalue, err := instance.Cast(value) - if err != nil { - return false, err - } - - for _, allowed := range instance.allowedValues { - if reflect.DeepEqual(cvalue, allowed) { - return true, nil - } - } - return false, nil -} - -func (instance *StateVarInstance) IsValidValue(value interface{}) (bool, error) { - cvalue, err := instance.Cast(value) - if err != nil { - return false, err - } - - inrange, err1 := instance.IsValueInRange(cvalue) - allowed, err2 := instance.IsValueAllowed(cvalue) - if err1 != nil || err2 != nil { - if err1 != nil { - err = err1 - } else { - err = err2 - } - } - return inrange && allowed, err -} - -func (instance *StateVarInstance) HasDescription() bool { - return len(instance.description) > 0 -} - -func (instance *StateVarInstance) Description() string { - return instance.description -} - -func (instance *StateVarInstance) Model() *StateVariable { - return instance.model -} - -func (instance *StateVarInstance) IsConstant() bool { - return !instance.modifiable -} - -func (instance *StateVarInstance) HasStep() bool { - return instance.step != nil -} - -func (instance *StateVarInstance) Step() interface{} { - return instance.step -} - -func (instance *StateVarInstance) Value() interface{} { - instance.mu.RLock() - defer instance.mu.RUnlock() - return instance.value -} - -func (instance *StateVarInstance) SetValue(val interface{}) error { - cval, err := instance.Cast(val) - - if err != nil { - return err - } - - if ok, err := instance.IsValidValue(cval); !ok || err != nil { - if err != nil { - return err - } - return fmt.Errorf("Not valid value %v for variable %s", cval, instance.Name()) - } - - instance.mu.Lock() - defer instance.mu.Unlock() - instance.previousValue = instance.value - instance.value = cval - - if instance.ShouldTriggerEvent() { - instance.service.EventToBeSent(instance.Name(), instance.Value()) - } - - return nil -} - -func (instance *StateVarInstance) Incr() error { - if instance.HasStep() { - value, err := instance.model.valueType.Add(instance.Value(), instance.Step()) - if err != nil { - return err - } - return instance.SetValue(value) - } - return fmt.Errorf( - "no step for variable %s:%s", - instance.service.Name(), - instance.Name(), - ) -} - -func (instance *StateVarInstance) Decr() error { - if instance.HasStep() { - value, err := instance.model.valueType.Sub(instance.Value(), instance.Step()) - if err != nil { - return err - } - return instance.SetValue(value) - } - return fmt.Errorf( - "no step for variable %s:%s", - instance.service.Name(), - instance.Name(), - ) -} - -// ShouldTriggerEvent vérifie toutes les conditions -func (instance *StateVarInstance) ShouldTriggerEvent() bool { - if instance.IsSendingEvents() { - for name, condition := range instance.model.eventConditions { - if !condition(instance) { - log.Debugf( - "State variable %s:%s event condition %s not true", - instance.service.Name(), - instance.Name(), - name, - ) - return false - } - } - - return true - } - return false -} - -func (sv *StateVarInstance) GenerateEvent() *etree.Element { - - // Construire le XML d'événement - propSet := etree.NewElement("e:propertyset") - propSet.CreateAttr("xmlns:e", "urn:schemas-upnp-org:event-1-0") - - prop := propSet.CreateElement("e:property") - elem := prop.CreateElement(sv.model.Name()) - elem.SetText(sv.valueToString(sv.Value())) - - return propSet - -} - -// ToXMLElement generates the complete XML representation of the state variable -// Returns an etree.Element that can be serialized to XML -func (sv *StateVarInstance) ToXMLElement() *etree.Element { - // Create root element - elem := etree.NewElement("stateVariable") - - // Add sendEvents attribute (UPnP eventing capability) - if sv.sendEvents { - elem.CreateAttr("sendEvents", "yes") // Enable event notifications - } else { - elem.CreateAttr("sendEvents", "no") // Disable event notifications - } - - name := elem.CreateElement("name") - name.SetText(sv.Name()) - - // Add data type element - dataType := elem.CreateElement("dataType") - dataType.SetText(sv.model.valueType.String()) // Set UPnP type name (e.g., "ui1", "boolean") - - // Add default value if specified - if sv.defaultValue != nil { - defaultValue := elem.CreateElement("defaultValue") - // Convert value to UPnP-compatible string representation - defaultValue.SetText(sv.valueToString(sv.defaultValue)) - } - - // Add value range constraints if defined - if sv.valueRange != nil { - rangeElem := elem.CreateElement("allowedValueRange") - - // Minimum boundary value - min := rangeElem.CreateElement("minimum") - min.SetText(sv.valueToString(sv.valueRange.min)) - - // Maximum boundary value - max := rangeElem.CreateElement("maximum") - max.SetText(sv.valueToString(sv.valueRange.max)) - - // Add step value if defined (for incremental controls) - if sv.step != nil { - step := rangeElem.CreateElement("step") - step.SetText(sv.valueToString(sv.step)) - } - } - - // Add allowed value list if defined - if len(sv.allowedValues) > 0 { - allowedList := elem.CreateElement("allowedValueList") - for _, value := range sv.allowedValues { - // Create individual elements - allowed := allowedList.CreateElement("allowedValue") - allowed.SetText(sv.valueToString(value)) - } - } - - // Add description if available - if sv.description != "" { - desc := elem.CreateElement("description") - desc.SetText(sv.description) // Human-readable description - } - - return elem -} - -// valueToString converts a value to its UPnP-compatible string representation -// Handles type-specific formatting for proper XML serialization -func (sv *StateVarInstance) valueToString(val interface{}) string { - if val == nil { - return "" // Safeguard against nil values - } - - // Type-specific formatting for UPnP compliance - switch sv.model.valueType { - case StateType_Boolean: - // Boolean: "1" for true, "0" for false (UPnP standard) - if b, ok := val.(bool); ok && b { - return "1" - } - return "0" - - case StateType_Date: - // Date: YYYY-MM-DD format - if t, ok := val.(time.Time); ok { - return t.Format("2006-01-02") - } - - case StateType_DateTime, StateType_DateTimeTZ: - // DateTime: ISO 8601 format with timezone - if t, ok := val.(time.Time); ok { - return t.Format(time.RFC3339) - } - - case StateType_Time, StateType_TimeTZ: - // Time: HH:MM:SS format - if t, ok := val.(time.Time); ok { - return t.Format("15:04:05") - } - - case StateType_BinBase64: - // Binary: Base64 encoding - if b, ok := val.([]byte); ok { - return base64.StdEncoding.EncodeToString(b) - } - - case StateType_BinHex: - // Binary: Hex encoding - if b, ok := val.([]byte); ok { - return hex.EncodeToString(b) - } - - case StateType_URI: - // URI: Full URL string - if u, ok := val.(*url.URL); ok { - return u.String() - } - - case StateType_UUID: - // UUID: Canonical string representation - if u, ok := val.(uuid.UUID); ok { - return u.String() - } - } - - // Default conversion for unsupported types or fallback - return fmt.Sprintf("%v", val) -} diff --git a/pmoupnp/devices/services/statevariables/statevalueinstanceset.go b/pmoupnp/devices/services/statevariables/statevalueinstanceset.go deleted file mode 100644 index 765c9a59..00000000 --- a/pmoupnp/devices/services/statevariables/statevalueinstanceset.go +++ /dev/null @@ -1,36 +0,0 @@ -package statevariables - -import ( - "iter" - - "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/objectstore" - "github.com/beevik/etree" -) - -type StateVarInstanceSet objectstore.ObjectSet[*StateVarInstance] - -func (m *StateVarInstanceSet) Insert(obj *StateVarInstance) error { - return (*objectstore.ObjectSet[*StateVarInstance])(m).Insert(obj) -} - -func (m *StateVarInstanceSet) InsertOrReplace(obj *StateVarInstance) { - (*objectstore.ObjectSet[*StateVarInstance])(m).InsertOrReplace(obj) -} - -func (m *StateVarInstanceSet) Contains(obj *StateVarInstance) bool { - return (*objectstore.ObjectSet[*StateVarInstance])(m).Contains(obj) -} - -func (m *StateVarInstanceSet) All() iter.Seq[*StateVarInstance] { - return (*objectstore.ObjectSet[*StateVarInstance])(m).All() -} - -func (m *StateVarInstanceSet) ToXMLElement() *etree.Element { - elem := etree.NewElement("serviceStateTable") - - for sv := range m.All() { - elem.AddChild(sv.ToXMLElement()) - } - - return elem -} diff --git a/pmoupnp/devices/services/statevariables/statevariable.go b/pmoupnp/devices/services/statevariables/statevariable.go deleted file mode 100644 index 90508f80..00000000 --- a/pmoupnp/devices/services/statevariables/statevariable.go +++ /dev/null @@ -1,423 +0,0 @@ -package statevariables - -import ( - "fmt" - "maps" - "reflect" - "slices" - "strings" - "time" - - log "github.com/sirupsen/logrus" -) - -type EventType string - -type StateConditionFunc func(instance *StateVarInstance) bool -type StringValueParser func(value string) (interface{}, error) -type ValueSerializer func(value interface{}) (string, error) - -type StateVariable struct { - name string // Name of the state value (e.g., "Volume", "Brightness") - valueType StateVarType // Type of state value, see the upnp/statevaluetype package for more information on this. - step interface{} // Step size for incremental state values (e.g., "10") - modifiable bool - eventConditions map[string]StateConditionFunc - description string - defaultValue interface{} - valueRange *ValueRange - allowedValues []interface{} - sendEvents bool - parse StringValueParser - marshal ValueSerializer -} - -// BitSize returns the number of bits that will be used to represent values -// when this type is used in an UPnP State Variable. The returned value can be -// either 8, 16, 24, 32, or 64, depending on whether t is Byte, Boolean, I2, Ui2, -// I4, Ui4 respectively. If none of these types match, it will return -1. -func (sv StateVariable) BitSize() int { - return sv.valueType.BitSize() -} - -// Name returns the state variable's name (e.g., "Volume", "Brightness"). -func (sv StateVariable) Name() string { - return sv.name -} - -func (sv StateVariable) TypeID() string { - return "StateVariable" -} - -// Type returns the UPnP data type of the state variable. -func (state *StateVariable) Type() StateVarType { - return state.valueType -} - -func (state *StateVariable) AddEventCondition(name string, condition StateConditionFunc) { - state.eventConditions[name] = condition -} - -func (state *StateVariable) DeleteEventConditions(name string) error { - if _, ok := state.eventConditions[name]; !ok { - return fmt.Errorf("%s: no such event condition (%s)", state.name, name) - } - delete(state.eventConditions, name) - return nil -} - -// ClearEventConditions réinitialise toutes les conditions -func (state *StateVariable) ClearEventConditions() { - state.eventConditions = make(map[string]StateConditionFunc) -} - -func (sv *StateVariable) SetMinDelta(minDelta interface{}) error { - if minDelta == nil { - return fmt.Errorf("%s: nil is an invalid minimum delta value", sv.name) - } - - minDelta, err := sv.Cast(minDelta) - if err != nil { - return fmt.Errorf("%s: invalid minimum delta value %v : %v", sv.name, minDelta, err) - } - - // mdf := func(instance *StateValueInstance) bool { - // o := instance.previousValue - // n := instance.value - - // r,err := instance.model.valueType.ValueRange(o, n) - - // if err != nil { - // return false - // } - - // return instance.model.valueType.InRange() - // } - - // sv.eventConditions["MinDelta"] = mdf - return nil -} - -func (state *StateVariable) SetDefault(value interface{}) error { - var err error - var valid bool - - if valid, err = state.IsValidValue(value); valid && err == nil { - cvalue, _ := state.valueType.Cast(value) - state.defaultValue = cvalue - log.Debugf("🐞 Setting default value for %v to %v", state.name, cvalue) - return nil - } - return fmt.Errorf("invalid default value for %v (%v) : %v", state.name, value, err) -} - -func (state *StateVariable) HasDefault() bool { - return state.defaultValue != nil -} - -func (state *StateVariable) DefaultValue() interface{} { - if !state.HasDefault() { - return state.valueType.DefaultValue() - } - - return state.defaultValue -} - -// HasRange indicates if a value range constraint is defined. -// Returns true if min/max boundaries are set. -func (state *StateVariable) HasRange() bool { - return state.valueRange != nil -} - -// Maximum returns the upper bound of the value range. -// Returns nil if no range is defined. -func (state *StateVariable) Maximum() interface{} { - if state.valueRange == nil { - return nil - } - return state.valueRange.max -} - -// Minimum returns the lower bound of the value range. -// Returns nil if no range is defined. -func (state *StateVariable) Minimum() interface{} { - if state.valueRange == nil { - return nil - } - return state.valueRange.min -} - -func (state *StateVariable) SetValueParser(parser StringValueParser) { - state.parse = parser -} - -// SetRange defines the inclusive value range [min, max]. -// Validates and casts values to the state variable's type. -// -// Parameters: -// -// min: Lower boundary value -// max: Upper boundary value -// -// Returns: -// -// error: If values can't be cast to the type or are nil -// -// Example: -// -// err := volumeState.SetRange(0, 100) // 0-100 range for volume -func (state *StateVariable) SetRange(min, max interface{}) error { - if min == nil || max == nil { - return fmt.Errorf("min and max must not be nil") - } - limits, err := state.valueType.ValueRange(min, max) - if err != nil { - return fmt.Errorf("setting range: %v", err) - } - state.valueRange = limits - - log.Debugf("🐞 Setting range of %s to [%v, %v]", state.name, min, max) - return nil -} - -// UpdateMinimalValue dynamically updates the lower range boundary. -// Requires an existing range to be set. -// -// Parameters: -// -// value: New minimum value -// -// Returns: -// -// error: If no range exists or value can't be cast -func (state *StateVariable) UpdateMinimalValue(value interface{}) error { - if state.valueRange == nil { - return fmt.Errorf("no range set for value %v", state.name) - } - cvalue, err := state.valueType.Cast(value) - if err != nil { - return fmt.Errorf("casting value: %v", err) - } - state.valueRange.min = cvalue - - log.Debugf("🐞 Updating minimal value of %s to %v", state.name, cvalue) - return nil -} - -// UpdateMaximalValue dynamically updates the upper range boundary. -// Requires an existing range to be set. -// -// Parameters: -// -// value: New maximum value -// -// Returns: -// -// error: If no range exists or value can't be cast -func (state *StateVariable) UpdateMaximalValue(value interface{}) error { - if state.valueRange == nil { - return fmt.Errorf("no range set for value %v", state.name) - } - cvalue, err := state.valueType.Cast(value) - if err != nil { - return fmt.Errorf("casting value: %v", err) - } - state.valueRange.max = cvalue - - log.Debugf("🐞 Updating maximal value of %s to %v", state.name, cvalue) - return nil -} - -// IsSendingEvents indicates if state changes trigger UPnP events. -func (state *StateVariable) IsSendingEvents() bool { - return state.sendEvents -} - -// SetSendingEvents enables event notifications for state changes. -func (state *StateVariable) SetSendingEvents() { - state.sendEvents = true - log.Debugf("🐞 Enabling event sending for %s", state.name) -} - -// UnsetSendingEvents disables event notifications for state changes. -func (state *StateVariable) UnsetSendingEvents() { - state.sendEvents = false - log.Debugf("🐞 Disabling event sending for %s", state.name) -} - -// HasAllowedValues indicates if an allowed value list is defined. -func (state *StateVariable) HasAllowedValues() bool { - return len(state.allowedValues) > 0 -} - -// AllowedValues returns the list of permitted values. -// Returns an empty slice if no values are defined. -func (state *StateVariable) AllowedValues() []interface{} { - return state.allowedValues -} - -// AppendAllowedValue adds values to the permitted value list. -// Values are cast to the state variable's type before adding. -// -// Parameters: -// -// value: One or more values to add -// -// Returns: -// -// error: If any value can't be cast to the type -// -// Example: -// -// err := state.AppendAllowedValue("PLAYING", "PAUSED", "STOPPED") -func (state *StateVariable) AppendAllowedValue(value ...interface{}) error { - state.allowedValues = slices.Grow(state.allowedValues, len(value)) - for _, v := range value { - cv, err := state.valueType.Cast(v) - if err != nil { - return fmt.Errorf("casting allowed value: %v", err) - } - state.allowedValues = append(state.allowedValues, cv) - } - - log.Debugf("🐞 Added allowed values to %s: %v", state.name, value) - return nil -} - -func (state *StateVariable) HasDescription() bool { - return len(state.description) > 0 -} - -func (state *StateVariable) Description() string { - return state.description -} - -func (state *StateVariable) SetDescription(desc string) { - state.description = strings.TrimSpace(desc) -} - -func (state *StateVariable) IsConstant() bool { - return !state.modifiable -} - -func (state *StateVariable) SetConstant() { - state.modifiable = false -} - -func (state *StateVariable) SetModifiable() { - state.modifiable = true -} - -func (state *StateVariable) SetStep(step interface{}) error { - // Validation que le step correspond au type de la variable - if _, err := state.valueType.Cast(step); err != nil { - return fmt.Errorf("invalid step type: %v", err) - } - state.step = step - return nil -} - -func (state *StateVariable) UnsetStep() { - state.step = nil -} - -func (state *StateVariable) HasStep() bool { - return state.step != nil -} - -func (state *StateVariable) Step() interface{} { - return state.step -} - -func (state *StateVariable) SetAllowedValues(allowed ...interface{}) { - state.ClearAllowedValues() - state.AppendAllowedValues(allowed...) -} - -func (state *StateVariable) AppendAllowedValues(allowed ...interface{}) error { - state.allowedValues = slices.Grow(state.allowedValues, len(allowed)) - - var err error - for _, val := range allowed { - val, err = state.valueType.Cast(val) - if err != nil { - return err - } - state.allowedValues = append(state.allowedValues, val) - } - return nil -} - -func (state *StateVariable) ClearAllowedValues() { - state.allowedValues = make([]interface{}, 0) -} - -// bool: True if within range or no range defined -func (state *StateVariable) IsValueInRange(value interface{}) (bool, error) { - return state.valueType.InRange(value, state.valueRange) -} - -func (state *StateVariable) IsValueAllowed(value interface{}) (bool, error) { - if !state.HasAllowedValues() { - return true, nil // No list = any value valid - } - cvalue, err := state.Cast(value) - if err != nil { - return false, err - } - - for _, allowed := range state.allowedValues { - if reflect.DeepEqual(cvalue, allowed) { - return true, nil - } - } - return false, nil -} - -func (state *StateVariable) IsValidValue(value interface{}) (bool, error) { - cvalue, err := state.Cast(value) - if err != nil { - return false, err - } - - inrange, err1 := state.IsValueInRange(cvalue) - allowed, err2 := state.IsValueAllowed(cvalue) - if err1 != nil || err2 != nil { - if err1 != nil { - err = err1 - } else { - err = err2 - } - } - return inrange && allowed, err -} - -func (state *StateVariable) NewInstance() *StateVarInstance { - instance := &StateVarInstance{ - model: state, - name: state.name, - modifiable: state.modifiable, - description: state.description, - step: state.step, - defaultValue: state.defaultValue, - - eventConditions: maps.Clone(state.eventConditions), - allowedValues: slices.Clone(state.allowedValues), - sendEvents: state.sendEvents, - parse: state.parse, - marshal: state.marshal, - - value: state.DefaultValue(), - lastChange: time.Now(), - lastEvent: time.Unix(int64(1718985600), 0).UTC(), - } - - if state.HasRange() { - instance.valueRange = &ValueRange{ - min: state.valueRange.min, - max: state.valueRange.max, - } - } - - return instance -} diff --git a/pmoupnp/devices/services/statevariables/statevariable_TransferStatus.go b/pmoupnp/devices/services/statevariables/statevariable_TransferStatus.go deleted file mode 100644 index 507e7098..00000000 --- a/pmoupnp/devices/services/statevariables/statevariable_TransferStatus.go +++ /dev/null @@ -1,17 +0,0 @@ -package statevariables - -var TransferStatus = func() *StateVariable { - - ts := StateType_String.NewStateValue("TransferStatus") - - ts.SetAllowedValues( - "COMPLETED", - "ERROR", - "IN_PROGRESS", - "NONE", - ) - - ts.SetSendingEvents() - - return ts -}() diff --git a/pmoupnp/devices/services/statevariables/statevariable_arithm.go b/pmoupnp/devices/services/statevariables/statevariable_arithm.go deleted file mode 100644 index a6a82eaf..00000000 --- a/pmoupnp/devices/services/statevariables/statevariable_arithm.go +++ /dev/null @@ -1,39 +0,0 @@ -package statevariables - -// Add performs addition operation on the given parameters 'a' and 'b'. It calls the -// corresponding method from valueType which is assumed to be an interface that -// provides methods for arithmetic operations. This function returns the result of -// the operation or an error if any occurs during computation. Side effects might -// include modifying the state of the system, but this depends on the actual implementation -// of the valueType's Add method. Errors might occur due to invalid input parameters or -// failures in the addition operation itself. The function does not handle edge cases -// and therefore should be used with caution. Here is an example usage: -// -// result, err := sv.Add(5, 3) -// if err != nil { -// // Handle error -// } else { -// // Use result -// } -func (sv StateVariable) Add(a, b interface{}) (interface{}, error) { - return sv.valueType.Add(a, b) -} - -// Sub performs subtraction operation on the given parameters 'a' and 'b'. It follows -// similar semantics as in the Add method, but for subtraction instead of addition. -func (sv StateVariable) Sub(a, b interface{}) (interface{}, error) { - return sv.valueType.Sub(a, b) -} - -// Mul performs multiplication operation on the given parameters 'a' and 'b'. It follows -// similar semantics as in the Add method, but for multiplication instead of addition. -func (sv StateVariable) Mul(a, b interface{}) (interface{}, error) { - return sv.valueType.Mul(a, b) -} - -// Div performs division operation on the given parameters 'a' and 'b'. It follows similar -// semantics as in the Add method, but for division instead of addition. Please note that -// division by zero is undefined and will result in an error being returned from valueType.Div call. -func (sv StateVariable) Div(a, b interface{}) (interface{}, error) { - return sv.valueType.Div(a, b) -} diff --git a/pmoupnp/devices/services/statevariables/statevariable_cast.go b/pmoupnp/devices/services/statevariables/statevariable_cast.go deleted file mode 100644 index a7fdac08..00000000 --- a/pmoupnp/devices/services/statevariables/statevariable_cast.go +++ /dev/null @@ -1,29 +0,0 @@ -package statevariables - -// Cast transforms any given value into an interface suitable for use in a StateValue object, using -// the underlying type's specific casting rules. It will return an error if the transformation fails or -// if the provided interface is not supported by the ValueType of the StateValue. -// This function does NOT mutate the original value it receives as input. -// -// The parameter 'val' is an interface that needs to be cast into a form compatible with the internal -// state representation used by the StateValue object. -// -// It returns an interface and an error: if the casting operation was successful, the first return value will -// be the casted version of 'val', and the second one (an error) will be nil. If the casting fails, it will -// return a nil for the first value and an appropriate error for the second one. -// -// This function should not modify its input value. It is idempotent and always returns consistent results given -// the same inputs. However, if the provided interface 'val' does not match with the ValueType of StateValue, it -// will return an error. -// -// Example usage: -// -// state := upnp.NewStateValue(upnp.NewTime()) -// castedVal, err := state.Cast("2022-12-31") -// if err != nil { -// log.Println(err) -// return -// } -func (sv *StateVariable) Cast(val interface{}) (interface{}, error) { - return sv.valueType.Cast(val) -} diff --git a/pmoupnp/devices/services/statevariables/statevariable_cmp.go b/pmoupnp/devices/services/statevariables/statevariable_cmp.go deleted file mode 100644 index f789825e..00000000 --- a/pmoupnp/devices/services/statevariables/statevariable_cmp.go +++ /dev/null @@ -1,13 +0,0 @@ -package statevariables - -func (sv StateVariable) Cmp(a, b interface{}) (int, error) { - return sv.valueType.Cmp(a, b) -} - -func (sv StateVariable) Equal(a, b interface{}) (int, error) { - return sv.valueType.Cmp(a, b) -} - -func (sv StateVariable) InRange(val interface{}, interval *ValueRange) (bool, error) { - return sv.valueType.InRange(val, interval) -} diff --git a/pmoupnp/devices/services/statevariables/statevariable_typechecking.go b/pmoupnp/devices/services/statevariables/statevariable_typechecking.go deleted file mode 100644 index a65859ea..00000000 --- a/pmoupnp/devices/services/statevariables/statevariable_typechecking.go +++ /dev/null @@ -1,158 +0,0 @@ -package statevariables - -// IsNumeric checks whether a given StateValue model represents a numeric value or -// not. Numeric types are defined as those that can be used to store number-like -// values. The following types are considered numeric: UI1, UI2, UI4, I1, I2, -// I4, Int, R4, R8, Number and Fixed14_4. -// -// t: StateVarType to check if it's a numeric type or not. -// -// Returns true if the given StateValue represents a numeric value; false -// otherwise. -func (sv StateVariable) IsNumeric() bool { - return sv.valueType.IsNumeric() -} - -// IsInteger checks if the state variable type is integer or not. -// -// It returns a boolean value indicating whether the provided StateValue -// is an integer type or not. -// -// Returns: bool: If the state variable type is any of the defined integer types -// (UI1, UI2, UI4, I1, I2, I4, Int), it returns true. Otherwise, it returns false. -func (sv StateVariable) IsInteger() bool { - return sv.valueType.IsInteger() -} - -// IsSignedInt checks if the state value type is a signed int. -// -// The return value will be a boolean indicating whether the state value type is -// a signed integer (true) or not (false). -func (sv StateVariable) IsSignedInt() bool { - return sv.valueType.IsSignedInt() -} - -// IsUnsignedInt checks if the state value type represents an unsigned integer. -// The method returns a boolean indicating whether the state value type is an -// unsigned integer. -func (sv StateVariable) IsUnsignedInt() bool { - return sv.valueType.IsUnsignedInt() -} - -// IsFloat returns true if the StateValue's value type represents a floating point -// number; false otherwise. -func (sv StateVariable) IsFloat() bool { - return sv.valueType.IsFloat() -} - -// IsBool checks if the state value is of boolean type. -// -// Parameters: -// -// None -// -// Returns: -// -// (bool) : Indicates whether the StateValue is of boolean type or not. -func (sv StateVariable) IsBool() bool { - return sv.valueType.IsBool() -} - -// IsString checks if the underlying value type of a StateValue object -// represents a string. -// -// Parameters: -// - None. -// -// Returns: -// -// bool: Indicates whether the underlying value type is a string or not. -// -// Side Effects: -// - This function does not modify any state. It only reads and returns a boolean value. -// -// Errors: -// - This function does not return an error, so you don't have to check for errors. -// -// Edge Cases: -// - If the underlying type of the StateValue is not TypeString, -// this function will return false as expected. -// -// Usage example: -// -// state := upnp.StateValue{valueType: upnp.TypeInt} -// fmt.Println(state.IsString()) // Outputs: false -func (sv StateVariable) IsString() bool { - return sv.valueType.IsString() -} - -// IsTime reports whether this state value represents a time instance. -// -// The function returns true if and only if the underlying type of the -// StateValue is TypeTime, else false. This method does not check for other -// types that are convertible to Time as it's assumed that these would be -// handled by the ConvertToType method beforehand. -// -// No side effects: this function is pure and doesn't change any state. -// -// Errors: This function does not return an error, so you don't have to check -// for errors. However, note that TypeTime conversion might fail if the -// StateValue isn't convertible to Time; use the ConvertToType method in such -// cases. -// -// Edge cases: If the underlying type of the StateValue is not TypeTime or is a -// non-convertible time, this function will return false as expected. -// -// Usage example: -// -// state := upnp.StateValue{valueType: upnp.TypeInt} -// fmt.Println(state.IsTime()) -// -// Outputs: false -func (sv StateVariable) IsTime() bool { - return sv.valueType.IsTime() -} - -// IsUUID checks if the state value type is a UUID (Universally Unique -// Identifier). -// -// It returns true if the underlying type of the StateValue object represents a -// UUID; false otherwise. -// -// Returns: bool: Indicates whether the StateValue is of UUID type or not. -func (sv StateVariable) IsUUID() bool { - return sv.valueType.IsUUID() -} - -// IsURI checks if the state value type is a URI. -// The method returns a boolean indicating whether the state value type represents -// a Uniform Resource Identifier (URI) or not. -// -// Returns: bool: Indicates whether the StateValue is of URI type or not. -func (sv StateVariable) IsURI() bool { - return sv.valueType.IsURI() -} - -// IsBinary checks if the state value type is binary or not. -// -// The function returns a boolean indicating whether the provided StateValue's -// value type is of binary format (bin.base64 or bin.hex). -// -// Returns: bool: If the underlying value type of the StateValue object is -// either TypeBinBase64 or TypeBinHex, this method will return true; otherwise, -// it returns false. -func (sv StateVariable) IsBinary() bool { - return sv.valueType.IsBinary() -} - -// IsComparable function checks if a state variable is comparable or not. -// -// It returns false for binary types (bin.base64 and bin.hex) -// as they are non-comparable. For all other types, it returns true indicating -// that these types can be compared. -// // -// Returns: bool: A boolean value indicating whether the given StateValue is -// comparable or not. True means it's comparable, False means it isn't. -func (sv StateVariable) IsComparable() bool { - return sv.valueType.IsComparable() -} diff --git a/pmoupnp/devices/services/statevariables/statevariableset.go b/pmoupnp/devices/services/statevariables/statevariableset.go deleted file mode 100644 index 4bd213a8..00000000 --- a/pmoupnp/devices/services/statevariables/statevariableset.go +++ /dev/null @@ -1,25 +0,0 @@ -package statevariables - -import ( - "iter" - - "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/objectstore" -) - -type StateVariableSet objectstore.ObjectSet[*StateVariable] - -func (m *StateVariableSet) Insert(obj *StateVariable) error { - return (*objectstore.ObjectSet[*StateVariable])(m).Insert(obj) -} - -func (m *StateVariableSet) InsertOrReplace(obj *StateVariable) { - (*objectstore.ObjectSet[*StateVariable])(m).InsertOrReplace(obj) -} - -func (set *StateVariableSet) Contains(obj *StateVariable) bool { - return (*objectstore.ObjectSet[*StateVariable])(set).Contains(obj) -} - -func (m *StateVariableSet) All() iter.Seq[*StateVariable] { - return (*objectstore.ObjectSet[*StateVariable])(m).All() -} diff --git a/pmoupnp/devices/services/statevariables/statevartype.go b/pmoupnp/devices/services/statevariables/statevartype.go deleted file mode 100644 index 170dcd5b..00000000 --- a/pmoupnp/devices/services/statevariables/statevartype.go +++ /dev/null @@ -1,194 +0,0 @@ -// package stateVariables provides comprehensive handling of UPnP state variable types. -// It includes type identification, value casting, comparison, and range validation -// for all standard UPnP state variable types. -package statevariables - -import ( - "strings" - "time" -) - -// StateVarType represents UPnP state variable types with corresponding Go type mappings. -type StateVarType int - -// Constants defining all supported UPnP state variable types -const ( - StateType_Unknown StateVarType = iota - StateType_UI1 // Unsigned 8-bit integer (Go: uint8) - StateType_UI2 // Unsigned 16-bit integer (Go: uint16) - StateType_UI4 // Unsigned 32-bit integer (Go: uint32) - StateType_I1 // Signed 8-bit integer (Go: int8) - StateType_I2 // Signed 16-bit integer (Go: int16) - StateType_I4 // Signed 32-bit integer (Go: int32) - StateType_Int // Synonymous with i4 (Go: int32) - StateType_R4 // 32-bit floating point (Go: float32) - StateType_R8 // 64-bit floating point (Go: float64) - StateType_Number // Synonymous with r8 (Go: float64) - StateType_Fixed14_4 // Fixed-point decimal (Go: float64) - StateType_Char // Single Unicode character (Go: rune) - StateType_String // Character string (Go: string) - StateType_Boolean // Boolean value (Go: bool) - StateType_BinBase64 // Base64-encoded binary (Go: []byte) - StateType_BinHex // Hex-encoded binary (Go: []byte) - StateType_Date // Date (YYYY-MM-DD) (Go: time.Time) - StateType_DateTime // DateTime without timezone (Go: time.Time) - StateType_DateTimeTZ // DateTime with timezone (Go: time.Time) - StateType_Time // Time without timezone (Go: time.Time) - StateType_TimeTZ // Time with timezone (Go: time.Time) - StateType_UUID // Universally unique identifier (Go: uuid.UUID) - StateType_URI // Uniform Resource Identifier (Go: *url.URL) -) - -// typeNames maps UPnP XML type names to StateVarType constants -var typeNames = map[string]StateVarType{ - "ui1": StateType_UI1, - "ui2": StateType_UI2, - "ui4": StateType_UI4, - "i1": StateType_I1, - "i2": StateType_I2, - "i4": StateType_I4, - "int": StateType_Int, - "r4": StateType_R4, - "r8": StateType_R8, - "number": StateType_Number, - "fixed.14.4": StateType_Fixed14_4, - "char": StateType_Char, - "string": StateType_String, - "boolean": StateType_Boolean, - "bin.base64": StateType_BinBase64, - "bin.hex": StateType_BinHex, - "date": StateType_Date, - "dateTime": StateType_DateTime, - "dateTime.tz": StateType_DateTimeTZ, - "time": StateType_Time, - "time.tz": StateType_TimeTZ, - "uuid": StateType_UUID, - "uri": StateType_URI, -} - -// typeStrings provides string representations for StateVarType constants -var typeStrings = [...]string{ - "unknown", - "ui1", - "ui2", - "ui4", - "i1", - "i2", - "i4", - "int", - "r4", - "r8", - "number", - "fixed.14.4", - "char", - "string", - "boolean", - "bin.base64", - "bin.hex", - "date", - "dateTime", - "dateTime.tz", - "time", - "time.tz", - "uuid", - "uri", -} - -// StateVarTypeFactory takes a string and attempts to build from it a valid -// StateVarType. The input string is cleaned before processing - -// leading/trailing spaces are trimmed, the case is lowered for comparison with -// known types, and if no match is found 'StateType_Unknown' is returned. -func StateVarTypeFactory(s string) StateVarType { - s = strings.ToLower(strings.TrimSpace(s)) - if val, ok := typeNames[s]; ok { - return val - } - return StateType_Unknown -} - -// String returns a string representation of the StateVarType. It defaults to -// "unknown" if the type is not recognized. -func (t StateVarType) String() string { - if int(t) >= 0 && int(t) < len(typeStrings) { - return typeStrings[t] - } - return "unknown" -} - -// BitSize returns the bit size of the StateVarType value, or -1 if not numeric. -// The possible return values are 8 for StateTypes I1, UI1, and 64 for others. -func (t StateVarType) BitSize() int { - // If t isn't numeric, return -1 - if !t.IsNumeric() { - return -1 - } - - // Check the value of t and return the appropriate bit size - switch t { - case StateType_I1, StateType_UI1: - return 8 - case StateType_I2, StateType_UI2: - return 16 - case StateType_I4, StateType_UI4, StateType_Int, StateType_R4: - return 32 - case StateType_R8, StateType_Number, StateType_Fixed14_4: - return 64 - default: - return 64 - } -} - -// NewStateValue creates and returns a new StateValue struct instance with the given name -// and the receiver's state variable type. The created StateValue is initialized with an -// empty map for event conditions. If name is an empty string, it will cause panic in later -// usage. Name is typically used to identify or represent a specific value or condition -// associated with the variable type 't'. -func (t StateVarType) NewStateValue(name string) *StateVariable { - return &StateVariable{ - name: name, - valueType: t, - eventConditions: make(map[string]StateConditionFunc), - } -} - -func (t StateVarType) DefaultValue() interface{} { - switch t { - case StateType_Unknown: - - case StateType_UI1, StateType_UI2, StateType_UI4: - return uint64(0) - - case StateType_I1, StateType_I2, StateType_I4, StateType_Int: - return int64(0) - - case StateType_R4, StateType_R8, StateType_Number, StateType_Fixed14_4: - return float64(0) - - case StateType_Char, StateType_String: - return "" - case StateType_Boolean: - return false - - case StateType_BinBase64: - return "" - case StateType_BinHex: - return "" - case StateType_Date: - return time.Unix(int64(1718985600), 0).UTC() - case StateType_DateTime: - return time.Unix(int64(1718985600), 0).UTC() - case StateType_DateTimeTZ: - return time.Unix(int64(1718985600), 0).UTC() - case StateType_Time: - return time.Unix(int64(1718985600), 0).UTC() - case StateType_TimeTZ: - return time.Unix(int64(1718985600), 0).UTC() - case StateType_UUID: - return "" - case StateType_URI: - return "" - - } - - return nil -} diff --git a/pmoupnp/devices/services/statevariables/statevartype_arithm.go b/pmoupnp/devices/services/statevariables/statevartype_arithm.go deleted file mode 100644 index 57b54df7..00000000 --- a/pmoupnp/devices/services/statevariables/statevartype_arithm.go +++ /dev/null @@ -1,73 +0,0 @@ -package statevariables - -// Add performs addition operation on two interfaces if both are of numeric -// type, otherwise it returns an error. If the types are not numeric, it checks -// and converts them into float64 before performing the addition. The function -// then casts the result back to its original type using Cast method from -// StateVarType t and returns this value or any encountered error. -// -// Parameters: -// -// a (interface{}): First operand for addition operation. Can be of any type. -// b (interface{}): Second operand for addition operation. Can be of any type. -// -// Returns: -// -// interface{}: Result of the addition, casted back to its original type using StateVarType t if no error encountered. -// error: Encountered error in case any conversion or casting fails. This includes non-numeric types for this operation. -func (t StateVarType) Add(a, b interface{}) (interface{}, error) { - af, bf, err := valuesToNumericOperands(t, a, b) - if err != nil { - return nil, err - } - - return t.Cast(af + bf) -} - -// Sub subtracts 'b' from 'a'. It converts both values to numeric types -// and then performs a subtraction operation, casting the result back to its -// original type. If either conversion fails or an unsupported type is used, -// it returns an error. -func (t StateVarType) Sub(a, b interface{}) (interface{}, error) { - af, bf, err := valuesToNumericOperands(t, a, b) - if err != nil { - return nil, err - } - - return t.Cast(af - bf) -} - -// Mul takes in two interface types 'a' and 'b', multiplies them together -// and returns the result along with any error encountered during this -// process. If either of the inputs is not compatible with numeric values, an -// error will be returned. The multiplication operation is performed between two -// numbers represented as 'float64' types (since Go does not support generic -// types on its own). The resulting value will be cast to the type represented -// by the receiver of this method 't'. If a casting error occurs, it will also -// be returned along with nil for the result. -func (t StateVarType) Mul(a, b interface{}) (interface{}, error) { - af, bf, err := valuesToNumericOperands(t, a, b) - if err != nil { - return nil, err - } - - return t.Cast(af * bf) -} - -// Div performs division between the provided arguments 'a' and 'b'. The function casts both operands to their numeric equivalents using valuesToNumericOperands() before performing the division. -// -// Parameters: -// - a: first operand of type interface{}, can be of any type, will be converted if necessary -// - b: second operand of type interface{}, can be of any type, will be converted if necessary -// -// Returns: -// - result: the division result in numeric form after casting it with function t.Cast() -// - err: error that might occur during the conversion or division operation -func (t StateVarType) Div(a, b interface{}) (interface{}, error) { - af, bf, err := valuesToNumericOperands(t, a, b) - if err != nil { - return nil, err - } - - return t.Cast(af / bf) -} diff --git a/pmoupnp/devices/services/statevariables/statevartype_cast.go b/pmoupnp/devices/services/statevariables/statevartype_cast.go deleted file mode 100644 index 49c11db8..00000000 --- a/pmoupnp/devices/services/statevariables/statevartype_cast.go +++ /dev/null @@ -1,153 +0,0 @@ -package statevariables - -import ( - "fmt" - "net/url" - "strings" - "time" - - "github.com/google/uuid" -) - -// Cast converts a value to the Go type corresponding to the UPnP type. -// Supports conversion from various primitive types and strings. -// Returns an error for unsupported conversions or invalid values. -// -// Examples: -// - StateType_UI2.Cast(42) // uint16(42), nil -// - StateType_Boolean.Cast("true") // true, nil -// - StateType_UI1.Cast(300) // nil, error (overflow) -func (t StateVarType) Cast(val interface{}) (interface{}, error) { - switch t { - case StateType_UI1: - v, err := toUint(val, 8) - if err != nil { - return nil, fmt.Errorf("cannot cast %v (%T) to UI1", val, val) - } - return uint8(v), nil - - case StateType_UI2: - v, err := toUint(val, 16) - if err != nil { - return nil, fmt.Errorf("cannot cast %v (%T) to UI2", val, val) - } - return uint16(v), nil - - case StateType_UI4: - v, err := toUint(val, 32) - if err != nil { - return nil, fmt.Errorf("cannot cast %v (%T) to UI4", val, val) - } - return uint32(v), nil - - case StateType_I1: - v, err := toInt(val, 8) - if err != nil { - return nil, fmt.Errorf("cannot cast %v (%T) to I1", val, val) - } - return int8(v), nil - - case StateType_I2: - v, err := toInt(val, 16) - if err != nil { - return nil, fmt.Errorf("cannot cast %v (%T) to I2", val, val) - } - return int16(v), nil - - case StateType_I4, StateType_Int: - v, err := toInt(val, 32) - if err != nil { - return nil, fmt.Errorf("cannot cast %v (%T) to I4", val, val) - } - return int32(v), nil - - case StateType_R4: - v, err := toFloat(val, 32) - if err != nil { - return nil, fmt.Errorf("cannot cast %v (%T) to R4", val, val) - } - return float32(v), nil - - case StateType_R8, StateType_Number, StateType_Fixed14_4: - v, err := toFloat(val, 64) - if err != nil { - return nil, fmt.Errorf("cannot cast %v (%T) to R8", val, val) - } - return v, nil - - case StateType_Boolean: - b, err := toBool(val) - if err != nil { - return nil, fmt.Errorf("cannot cast %v (%T) to Boolean", val, val) - } - return b, nil - - case StateType_Char: - switch s := val.(type) { - case string: - if len(s) != 1 { - return nil, fmt.Errorf("invalid Char: string too long %q", s) - } - return rune(s[0]), nil - case rune: - return s, nil - default: - return nil, fmt.Errorf("cannot cast %v (%T) to Char", val, val) - } - - case StateType_String: - return fmt.Sprint(val), nil - - case StateType_UUID: - switch val := val.(type) { - case uuid.UUID: - return val, nil - case string: - u, err := uuid.Parse(strings.TrimSpace(val)) - if err != nil { - return nil, fmt.Errorf("invalid UUID %v: %v", val, err) - } - return u, nil - default: - return nil, fmt.Errorf("cannot cast %v (%T) to UUID", val, val) - } - - case StateType_URI: - switch val := val.(type) { - case *url.URL: - return val, nil - case string: - u, err := url.Parse(strings.TrimSpace(val)) - if err != nil { - return nil, fmt.Errorf("invalid URI %v: %v", val, err) - } - return u, nil - default: - return nil, fmt.Errorf("cannot cast %v (%T) to URI", val, val) - } - - case StateType_BinBase64, StateType_BinHex: - switch v := val.(type) { - case []byte: - return v, nil - case string: - return decodeBinary(t, v) - default: - return nil, fmt.Errorf("cannot cast %v (%T) to binary", val, val) - } - - case StateType_Date, StateType_DateTime, StateType_DateTimeTZ, - StateType_Time, StateType_TimeTZ: - switch v := val.(type) { - case time.Time: - return v, nil - case string: - return parseUPnPTime(t, v) - default: - return nil, fmt.Errorf("cannot cast %v (%T) to time", val, val) - } - - default: - return nil, fmt.Errorf("unsupported type: %v", t) - } -} diff --git a/pmoupnp/devices/services/statevariables/statevartype_cmp.go b/pmoupnp/devices/services/statevariables/statevartype_cmp.go deleted file mode 100644 index 03976831..00000000 --- a/pmoupnp/devices/services/statevariables/statevartype_cmp.go +++ /dev/null @@ -1,205 +0,0 @@ -package statevariables - -import ( - "bytes" - "fmt" - "log" - "strings" -) - -// Cmp compares two values of a given type 'StateVarType'. The comparison is -// made based on the specific type of 'a' and 'b'. It returns an integer -// indicating whether 'a' is less than, equal to, or greater than 'b'. If 'a' is -// less than 'b', it returns -1. If they are equal, it returns 0. If 'a' is -// greater than 'b', it returns 1. It also returns an error if any of the values -// can't be cast to the required type or if comparison isn't supported for the -// given type 'StateVarType'. -// -// - t: StateVarType representing the specific type to use for comparison. -// - a, b: The values to compare. They should be of type interface{} as they could be -// any valid Go type. -// -// Returns: An integer indicating the result of the comparison (-1 if 'a' is -// less than 'b', 0 if they are equal, and 1 if 'a' is greater than 'b'). It -// also returns an error if any values can't be cast or if comparison isn't -// supported for the given type. -// -// Example: -// -// result, err := t.Cmp(int32(5), int32(7)) // Returns -1 and nil error as 5 is less than 7. -func (t StateVarType) Cmp(a, b interface{}) (int, error) { - a, err1 := t.Cast(a) - b, err2 := t.Cast(b) - - if err1 != nil || err2 != nil { - log.Fatalf("Failed to cast for comparison: %v vs %v (errors: %v, %v)", a, b, err1, err2) - } - - switch { - case t.IsInteger(): - ai, err := toInt(a, t.BitSize()) - if err != nil { - return 0, fmt.Errorf("invalid int value for a: %w", err) - } - bi, err := toInt(b, t.BitSize()) - if err != nil { - return 0, fmt.Errorf("invalid int value for b: %w", err) - } - return cmpInt(ai, bi), nil - - case t.IsUnsignedInt(): - ai, err := toUint(a, t.BitSize()) - if err != nil { - return 0, fmt.Errorf("invalid uint value for a: %w", err) - } - bi, err := toUint(b, t.BitSize()) - if err != nil { - return 0, fmt.Errorf("invalid uint value for b: %w", err) - } - return cmpUint(ai, bi), nil - - case t.IsFloat(): - af, err := toFloat(a, t.BitSize()) - if err != nil { - return 0, fmt.Errorf("invalid float value for a: %w", err) - } - bf, err := toFloat(b, t.BitSize()) - if err != nil { - return 0, fmt.Errorf("invalid float value for b: %w", err) - } - return cmpFloat64(af, bf), nil - - case t == StateType_Boolean: - ab, err := toBool(a) - if err != nil { - return 0, fmt.Errorf("invalid bool value for a: %w", err) - } - bb, err := toBool(b) - if err != nil { - return 0, fmt.Errorf("invalid bool value for b: %w", err) - } - return cmpBool(ab, bb), nil - - case t == StateType_String || t == StateType_Char: - as, err := toString(a) - if err != nil { - return 0, fmt.Errorf("invalid string value for a") - } - bs, err := toString(b) - if err != nil { - return 0, fmt.Errorf("invalid string value for b") - } - return strings.Compare(as, bs), nil - - case t.IsTime(): - at, err := toTime(a) - if err != nil { - return 0, fmt.Errorf("invalid time value for a") - } - bt, err := toTime(b) - if err != nil { - return 0, fmt.Errorf("invalid time value for b") - } - return cmpTime(at, bt), nil - - default: - return 0, fmt.Errorf("comparison not supported for type %v", t) - } -} - -func (t StateVarType) Equal(a, b interface{}) (bool, error) { - switch { - case t.IsInteger(): - ai, err1 := toInt(a, 64) - bi, err2 := toInt(b, 64) - if err1 != nil || err2 != nil { - return false, fmt.Errorf("invalid integer value for type %s", t.String()) - } - return ai == bi, nil - - case t.IsFloat(): - af, err := toFloat(a, 64) - if err != nil { - return false, fmt.Errorf("invalid float value for type %s: %v", t.String(), err) - } - bf, err := toFloat(b, 64) - if err != nil { - return false, fmt.Errorf("invalid float value for type %s: %v", t.String(), err) - } - return af == bf, nil - - case t.IsString(): - as, ok1 := a.(string) - bs, ok2 := b.(string) - if !ok1 || !ok2 { - return false, fmt.Errorf("invalid string value for type %s", t.String()) - } - return as == bs, nil - - case t.IsBool(): - ab, err1 := toBool(a) - bb, err2 := toBool(b) - if err1 != nil || err2 != nil { - return false, fmt.Errorf("invalid boolean value for type %s", t.String()) - } - return ab == bb, nil - - case t.IsTime(): - at, err1 := toTime(a) - bt, err2 := toTime(b) - if err1 != nil || err2 != nil { - return false, fmt.Errorf("invalid time.Time value for type %s", t.String()) - } - return at.Equal(bt), nil - - case t.IsUUID(): - au, err1 := toUUID(a) - bu, err2 := toUUID(b) - if err1 != nil || err2 != nil { - return false, fmt.Errorf("invalid uuid.UUID value for type %s", t.String()) - } - return au == bu, nil - - case t.IsURI(): - au, err1 := toURI(a) - bu, err2 := toURI(b) - if err1 != nil || err2 != nil { - return false, fmt.Errorf("invalid *url.URL value for type %s", t.String()) - } - return au.String() == bu.String(), nil - - case t.IsBinary(): - ab, err1 := toBinary(a) - bb, err2 := toBinary(b) - if err1 != nil || err2 != nil { - return false, fmt.Errorf("invalid []byte value for type %s", t.String()) - } - return bytes.Equal(ab, bb), nil - - default: - return false, fmt.Errorf("equality not supported for type %s", t.String()) - } -} - -// InRange checks if a value falls within an inclusive range [min, max]. -// Uses the type's comparison logic. Returns true if val is between min and max (inclusive). -// -// Example: -// -// range := ValueRange{min: uint16(10), max: uint16(100)} -// StateType_UI2.InRange(uint16(50), range) // true -func (t StateVarType) InRange(val interface{}, interval *ValueRange) (bool, error) { - if interval == nil { - return true, nil - } - cmp1, err1 := t.Cmp(val, interval.min) - cmp2, err2 := t.Cmp(val, interval.max) - if err1 != nil || err2 != nil { - err := err1 - if err == nil { - err = err2 - } - return false, err - } - return cmp1 >= 0 && cmp2 <= 0, nil -} diff --git a/pmoupnp/devices/services/statevariables/statevartype_typechecking.go b/pmoupnp/devices/services/statevariables/statevartype_typechecking.go deleted file mode 100644 index e741076e..00000000 --- a/pmoupnp/devices/services/statevariables/statevartype_typechecking.go +++ /dev/null @@ -1,171 +0,0 @@ -package statevariables - -// IsNumeric checks whether a given StateVarType represents a numeric type or -// not. Numeric types are defined as those that can be used to store number-like -// values. The following types are considered numeric: UI1, UI2, UI4, I1, I2, -// I4, Int, R4, R8, Number and Fixed14_4. -// -// t: StateVarType to check if it's a numeric type or not. -// -// Returns true if the given StateVarType represents a numeric type; false -// otherwise. -func (t StateVarType) IsNumeric() bool { - switch t { - case StateType_UI1, StateType_UI2, StateType_UI4, - StateType_I1, StateType_I2, StateType_I4, - StateType_Int, - StateType_R4, StateType_R8, - StateType_Number, - StateType_Fixed14_4: - return true - default: - return false - } -} - -// IsInteger checks if the state variable type is integer or not. -// -// It returns a boolean value indicating whether the provided StateVarType (t) -// is an integer type or not. The function takes one parameter, t of type -// StateVarType, which represents the state variable type to be checked. -// -// Parameters: - t (StateVarType): The StateVarType to check for comparability. -// -// Returns: bool: If the state variable type is any of the defined integer types -// (StateType_UI1, StateType_UI2, StateType_UI4, StateType_I1, StateType_I2, -// StateType_I4, StateType_Int), it returns true. Otherwise, it returns false. -func (t StateVarType) IsInteger() bool { - switch t { - case StateType_UI1, StateType_UI2, StateType_UI4, - StateType_I1, StateType_I2, StateType_I4, - StateType_Int: - return true - default: - return false - } -} - -// IsSignedInt checks if the state variable type is a signed integer type. -// The function returns true for StateType_I1, StateType_I2, StateType_I4, and -// StateType_Int, otherwise it will return false. This method is part of the -// StateVarType enumeration in statevaluetype package. It takes no parameters -// but operates on the receiver 't' of type StateVarType. -// -// The returned value is a boolean. -func (t StateVarType) IsSignedInt() bool { - switch t { - case StateType_I1, StateType_I2, StateType_I4, StateType_Int: - return true - default: - return false - } -} - -// IsUnsignedInt checks if the state variable type is an unsigned integer. It -// returns a boolean indicating whether or not the current StateVarType -// represents an unsigned integer type, namely: StateType_UI1, StateType_UI2, -// and StateType_UI4. -func (t StateVarType) IsUnsignedInt() bool { - switch t { - case StateType_UI1, StateType_UI2, StateType_UI4: - return true - default: - return false - } -} - -// IsFloat returns a boolean indicating whether the given state variable type -// represents a float number. If the state variable type is one of R4, R8, Number or -// Fixed14_4 it returns true; otherwise, it returns false. -func (t StateVarType) IsFloat() bool { - switch t { - case StateType_R4, StateType_R8, StateType_Number, StateType_Fixed14_4: - return true - default: - return false - } -} - -// IsBool checks if a StateVarType is of type Boolean. It returns true if the -// StateVarType equals to StateType_Boolean, false otherwise. -func (t StateVarType) IsBool() bool { - return t == StateType_Boolean -} - -// IsString reports whether or not the state variable type represents a string -// value. -// -// This method returns true if the StateVarType is either StateType_String or -// StateType_Char, otherwise it returns false. -func (t StateVarType) IsString() bool { - switch t { - case StateType_String, StateType_Char: - return true - default: - return false - } -} - -// IsTime checks whether a given StateVarType is of time type or not. It accepts -// a StateVarType parameter 't' and returns a boolean value based on the check. -// -// The possible values for 't' are: StateType_Date, StateType_DateTime, -// StateType_DateTimeTZ, StateType_Time, StateType_TimeTZ. If 't' is any of -// these types, the function returns true; otherwise, it returns false. -func (t StateVarType) IsTime() bool { - switch t { - case StateType_Date, StateType_DateTime, StateType_DateTimeTZ, - StateType_Time, StateType_TimeTZ: - return true - default: - return false - } -} - -// IsUUID reports whether the receiver represents a UUID (Universally Unique -// Identifier). The StateVarType should be of type StateType_UUID to return -// true. Otherwise, it returns false. -func (t StateVarType) IsUUID() bool { - return t == StateType_UUID -} - -// IsURI checks if the given state variable type is a URI. -// -// This function returns true if and only if the receiver (StateVarType t) -// equals StateType_URI, which represents URIs in UPnP protocol. Otherwise, it -// returns false. -func (t StateVarType) IsURI() bool { - return t == StateType_URI -} - -// IsBinary checks if the given StateVarType is binary type or not. It returns -// true for types StateType_BinBase64 and StateType_BinHex, otherwise it returns -// false. -func (t StateVarType) IsBinary() bool { - switch t { - case StateType_BinBase64, StateType_BinHex: - return true - default: - return false - } -} - -// IsComparable function checks if a StateVarType is comparable or not. -// -// It returns false for binary types (StateType_BinBase64 and StateType_BinHex) -// as they are non-comparable. For all other types, it returns true indicating -// that these types can be compared. -// -// Parameters: - t (StateVarType): The StateVarType to check for comparability. -// -// Returns: bool: A boolean value indicating whether the given StateVarType is -// comparable or not. True means it's comparable, False means it isn't. -func (t StateVarType) IsComparable() bool { - // Tous les types sauf les binaires sont comparables - switch t { - case StateType_BinBase64, StateType_BinHex: - return false - default: - return true - } -} diff --git a/pmoupnp/devices/services/statevariables/utils_binary.go b/pmoupnp/devices/services/statevariables/utils_binary.go deleted file mode 100644 index 7bfaaa10..00000000 --- a/pmoupnp/devices/services/statevariables/utils_binary.go +++ /dev/null @@ -1,62 +0,0 @@ -package statevariables - -import ( - "encoding/base64" - "encoding/hex" - "fmt" - "strings" -) - -// toBinary tries to convert v into a []byte. -// - if v is []byte, returns it directly -// - if v is string, attempts base64 decode, then hex decode -func toBinary(v interface{}) ([]byte, error) { - switch val := v.(type) { - case []byte: - return val, nil - - case string: - // Try base64 first - if data, err := base64.StdEncoding.DecodeString(val); err == nil { - return data, nil - } - - // Try hex next - if data, err := hex.DecodeString(val); err == nil { - return data, nil - } - - return nil, fmt.Errorf("cannot parse string as base64 or hex: %q", val) - - default: - return nil, fmt.Errorf("cannot convert type %T to binary", v) - } -} - -// decodeBinary decodes Base64 or Hex-encoded binary strings to byte slices -func decodeBinary(t StateVarType, val string) ([]byte, error) { - switch t { - case StateType_BinBase64: - data, err := base64.StdEncoding.DecodeString(val) - if err != nil { - return nil, fmt.Errorf("invalid base64: %v", err) - } - return data, nil - - case StateType_BinHex: - // Accept even-length hex string - val = strings.TrimSpace(val) - if len(val)%2 != 0 { - return nil, fmt.Errorf("invalid hex: odd-length string") - } - data := make([]byte, len(val)/2) - _, err := hex.Decode(data, []byte(val)) - if err != nil { - return nil, fmt.Errorf("invalid hex: %v", err) - } - return data, nil - - default: - return nil, fmt.Errorf("decodeBinary: unsupported binary type %v", t) - } -} diff --git a/pmoupnp/devices/services/statevariables/utils_bool.go b/pmoupnp/devices/services/statevariables/utils_bool.go deleted file mode 100644 index f0e24608..00000000 --- a/pmoupnp/devices/services/statevariables/utils_bool.go +++ /dev/null @@ -1,61 +0,0 @@ -package statevariables - -import ( - "errors" - "strings" -) - -// parseUPnPBoolean parses a string like "true", "false", "1", "0" into a boolean. -func parseUPnPBoolean(s string) (bool, error) { - switch strings.ToLower(strings.TrimSpace(s)) { - case "1", "true": - return true, nil - case "0", "false": - return false, nil - default: - return false, errors.New("invalid string for UPnP boolean") - } -} - -// toBool converts various types to boolean following UPnP rules: -// true: 1, "true"; false: 0, "false" -func toBool(val interface{}) (bool, error) { - if val == nil { - return false, errors.New("cannot convert nil to bool") - } - - switch v := val.(type) { - case bool: - return v, nil - - case string: - return parseUPnPBoolean(v) - - default: - // try to convert numerics to float - f, err := toFloat(v, 64) - if err != nil { - return false, err - } - - if f == 1.0 { - return true, nil - } - if f == 0.0 { - return false, nil - } - return false, errors.New("numeric value cannot be converted to bool unless 0 or 1") - } -} - -// cmpBool compares two boolean values 'a' and 'b'. If they are equal it returns 0, if 'a' is false and 'b' is true it returns -1 else it returns 1. -func cmpBool(a, b bool) int { - if a == b { // if both booleans are the same, return 0 - return 0 - } - if !a && b { // if 'a' is false and 'b' is true, return -1 - return -1 - } - // otherwise, return 1 - return 1 // if 'a' is true or 'a' and 'b' are not the same -} diff --git a/pmoupnp/devices/services/statevariables/utils_float.go b/pmoupnp/devices/services/statevariables/utils_float.go deleted file mode 100644 index 72f73997..00000000 --- a/pmoupnp/devices/services/statevariables/utils_float.go +++ /dev/null @@ -1,95 +0,0 @@ -package statevariables - -import ( - "fmt" - "math" - "strconv" -) - -// maxFloat returns the maximum value for floating point numbers given number of bits. -// If bits is neither 32 nor 64, it defaults to returning the maximum float64 value. -func maxFloat(bits int) float64 { - switch bits { - case 32: - return float64(math.MaxFloat32) - case 64: - return math.MaxFloat64 - default: - return math.MaxFloat64 // fallback - } -} - -// minFloat returns the minimum float value for the given number of bits. -// If bits are not recognized as either 32 or 64, it will default to the maximum -// possible float64 value. -func minFloat(bits int) float64 { - switch bits { - case 32: - return -float64(math.MaxFloat32) - case 64: - return -math.MaxFloat64 - default: - return -math.MaxFloat64 // fallback - } -} - -// toFloat converts various types to float (32 or 64 bits). -// Checks float32 boundaries when converting to 32-bit float. -// toFloat converts v to a float64, ensuring it fits within the range of the requested float size. -func toFloat(v interface{}, bits int) (float64, error) { - var f float64 - - switch val := v.(type) { - case float32: - f = float64(val) - case float64: - f = val - case int: - f = float64(val) - case int8: - f = float64(val) - case int16: - f = float64(val) - case int32: - f = float64(val) - case int64: - f = float64(val) - case uint: - f = float64(val) - case uint8: - f = float64(val) - case uint16: - f = float64(val) - case uint32: - f = float64(val) - case uint64: - f = float64(val) - case string: - var err error - f, err = strconv.ParseFloat(val, bits) - if err != nil { - return 0, err - } - default: - return 0, fmt.Errorf("%T,unsupported type in toFloat", v) - } - - if f < minFloat(bits) || f > maxFloat(bits) { - return 0, fmt.Errorf("value %v overflows float%d range", v, bits) - } - - return f, nil -} - -// cmpFloat64 compares two float64 values and returns an integer indicating their relation. -// If a is less than b, it returns -1; if a is greater than b, it returns 1; otherwise, it returns 0. -func cmpFloat64(a, b float64) int { - switch { - case a < b: - return -1 - case a > b: - return 1 - default: - return 0 - } -} diff --git a/pmoupnp/devices/services/statevariables/utils_int.go b/pmoupnp/devices/services/statevariables/utils_int.go deleted file mode 100644 index c89daa3e..00000000 --- a/pmoupnp/devices/services/statevariables/utils_int.go +++ /dev/null @@ -1,143 +0,0 @@ -package statevariables - -import ( - "errors" - "math" - "reflect" - "strconv" -) - -// minInt returns minimum signed integer value for specified bit size -func minInt(bits int) int64 { - switch bits { - case 8: - return math.MinInt8 - case 16: - return math.MinInt16 - case 32: - return math.MinInt32 - case 64: - return math.MinInt64 - default: - return math.MinInt64 // fallback - } -} - -// maxInt returns maximum signed integer value for specified bit size -func maxInt(bits int) int64 { - switch bits { - case 8: - return math.MaxInt8 - case 16: - return math.MaxInt16 - case 32: - return math.MaxInt32 - case 64: - return math.MaxInt64 - default: - return math.MaxInt64 // fallback - } -} - -// toInt converts the given interface value into an int64. The function accepts -// a parameter v of any type and an integer bits representing the size of the -// desired integer type (8, 16, 32 or 64). If successful, it returns the -// converted integer and nil for error. Otherwise, it returns zero for int64 and -// an appropriate error message. -// -// The function checks whether v is nil. If true, it returns an error stating -// "cannot convert nil to int". -// -// It then identifies the type of v using a type switch statement. Depending on -// the type, the function performs different actions: -// - For integer types (int, int8, int16, int32 and int64), it uses checkIntBounds() to ensure the value fits within the specified bits range and returns the result. -// - For unsigned types (uint, uint8, uint16, uint32 and uint64), it checks for overflow before converting to an int64 and calls checkIntBounds(). -// - For float types (float32 and float64), it converts them to int64 directly. -// - For string type, it attempts to parse the string as a base-10 integer using strconv.ParseInt() with specified bits range. -// -// If no match is found in these cases or v is of unsupported type, it returns -// an error stating "unsupported type for toInt". -func toInt(v interface{}, bits int) (int64, error) { - if v == nil { - return 0, errors.New("cannot convert nil to int") - } - - switch val := v.(type) { - case int: - return checkIntBounds(int64(val), bits) - case int8: - return checkIntBounds(int64(val), bits) - case int16: - return checkIntBounds(int64(val), bits) - case int32: - return checkIntBounds(int64(val), bits) - case int64: - return checkIntBounds(val, bits) - - case uint, uint8, uint16, uint32, uint64: - u := reflect.ValueOf(val).Uint() - if u > uint64(math.MaxInt64) { - return 0, errors.New("unsigned value overflows int64") - } - return checkIntBounds(int64(u), bits) - - case float32: - return checkIntBounds(int64(val), bits) - case float64: - return checkIntBounds(int64(val), bits) - - case string: - i, err := strconv.ParseInt(val, 10, bits) - if err != nil { - return 0, err - } - return checkIntBounds(i, bits) - - default: - return 0, errors.New("unsupported type for toInt") - } -} - -// CheckIntBounds checks if a given int64 value is within the valid range for a specific number of bits. -// It returns an error and 0 if the value is out of bounds, else it returns the input value and nil. -// -// Parameters: -// - v: The integer value to check. -// - bits: The number of bits that determine the valid range for 'v'. -// -// Returns: -// - int64: The original input value if within bounds, else 0. -// - error: An error object if the value is out of bounds; nil otherwise. -func checkIntBounds(v int64, bits int) (int64, error) { - if v < minInt(bits) || v > maxInt(bits) { - return 0, errors.New("integer value out of bounds") - } - return v, nil -} - -// cmpInt compares two integers 'a' and 'b'. If 'a' is less than 'b', it returns -1, if 'a' is greater than 'b' it returns 1, else it returns 0. -func cmpInt(a, b int64) int { - switch { - case a < b: - return -1 - case a > b: - return 1 - default: - return 0 - } -} - -// cmpUint compares two unsigned integers, a and b. -// It returns -1 if a < b. -// It returns 1 if a > b. -// It returns 0 if a == b. -func cmpUint(a, b uint64) int { - switch { - case a < b: - return -1 - case a > b: - return 1 - default: - return 0 - } -} diff --git a/pmoupnp/devices/services/statevariables/utils_numeric_operandes.go b/pmoupnp/devices/services/statevariables/utils_numeric_operandes.go deleted file mode 100644 index 1cacd410..00000000 --- a/pmoupnp/devices/services/statevariables/utils_numeric_operandes.go +++ /dev/null @@ -1,32 +0,0 @@ -package statevariables - -import "fmt" - -// valuesToNumericOperands takes two interface{} values, casts them to a numeric type based on a given StateVarType, and returns their float64 equivalents. -// If any error occurs during casting or conversion to float64, it is returned along with zero values for the operands. -func valuesToNumericOperands(t StateVarType, a interface{}, b interface{}) (float64, float64, error) { - var err error - if !t.IsNumeric() { - return 0, 0, fmt.Errorf("type %v is not numeric", t) - } - - a, err = t.Cast(a) - if err != nil { - return 0, 0, err - } - - b, err = t.Cast(b) - if err != nil { - return 0, 0, err - } - - af, err := toFloat(a, 64) - if err != nil { - return 0, 0, err - } - bf, err := toFloat(b, 64) - if err != nil { - return 0, 0, err - } - return af, bf, nil -} diff --git a/pmoupnp/devices/services/statevariables/utils_string.go b/pmoupnp/devices/services/statevariables/utils_string.go deleted file mode 100644 index 6564faf3..00000000 --- a/pmoupnp/devices/services/statevariables/utils_string.go +++ /dev/null @@ -1,37 +0,0 @@ -package statevariables - -import ( - "fmt" -) - -// toString converts v to string if possible. -func toString(v interface{}) (string, error) { - switch val := v.(type) { - case string: - return val, nil - - case []byte: - return string(val), nil - - case fmt.Stringer: - return val.String(), nil - - case int, int8, int16, int32, int64: - return fmt.Sprintf("%d", val), nil - - case uint, uint8, uint16, uint32, uint64: - return fmt.Sprintf("%d", val), nil - - case float32, float64: - return fmt.Sprintf("%v", val), nil - - case bool: - if val { - return "true", nil - } - return "false", nil - - default: - return "", fmt.Errorf("cannot convert type %T to string", v) - } -} diff --git a/pmoupnp/devices/services/statevariables/utils_time.go b/pmoupnp/devices/services/statevariables/utils_time.go deleted file mode 100644 index 58405d4f..00000000 --- a/pmoupnp/devices/services/statevariables/utils_time.go +++ /dev/null @@ -1,104 +0,0 @@ -package statevariables - -import ( - "fmt" - "strings" - "time" -) - -// toTime converts the given value to a time.Time type if possible, otherwise it returns an error. -// The supported types for conversion are: time.Time, string, int64 and float64. -func toTime(v interface{}) (time.Time, error) { - switch val := v.(type) { - case time.Time: - return val, nil - - case string: - // Liste de layouts communs à UPnP / ISO-8601 / RFC - layouts := []string{ - time.RFC3339Nano, // 2006-01-02T15:04:05.999999999Z07:00 - time.RFC3339, // 2006-01-02T15:04:05Z07:00 - "2006-01-02", // date only - "15:04:05", // time only - "15:04:05Z07:00", // time with TZ - "2006-01-02T15:04:05", // no TZ - "2006-01-02T15:04:05Z", // UTC - "2006-01-02 15:04:05", // space-separated - } - - for _, layout := range layouts { - if t, err := time.Parse(layout, val); err == nil { - return t, nil - } - } - return time.Time{}, fmt.Errorf("cannot parse time string: %q", val) - - case int64: - return time.Unix(val, 0), nil - - case float64: - sec := int64(val) - nsec := int64((val - float64(sec)) * 1e9) - return time.Unix(sec, nsec), nil - - default: - return time.Time{}, fmt.Errorf("unsupported type for time conversion: %T", v) - } -} - -// parseUPnPTime parses time values using UPnP-specific formats: -// - Date: "2006-01-02" -// - Time: "15:04:05" -// - DateTime: "2006-01-02T15:04:05" -// - TimeTZ: "15:04:05-07:00" -// - DateTimeTZ: "2006-01-02T15:04:05-07:00" -func parseUPnPTime(t StateVarType, s string) (time.Time, error) { - s = strings.TrimSpace(s) - - var layouts []string = nil - - switch t { - case StateType_Date: - layouts = []string{"2006-01-02"} - - case StateType_Time: - layouts = []string{"15:04:05"} // HH:MM:SS - - case StateType_TimeTZ: - layouts = []string{"15:04:05Z07:00"} // HH:MM:SS+TZ - - case StateType_DateTime: - layouts = []string{"2006-01-02T15:04:05"} // ISO8601 sans TZ - - case StateType_DateTimeTZ: - layouts = []string{ - "2006-01-02T15:04:05Z07:00", // full - "2006-01-02T15:04:05-0700", // fallback no colon - "2006-01-02T15:04:05Z", // Zulu - } - - default: - return time.Time{}, fmt.Errorf("unsupported date/time type: %v", t) - } - - for _, layout := range layouts { - if ts, err := time.Parse(layout, s); err == nil { - return ts, nil - } - } - - return time.Time{}, fmt.Errorf("invalid %v value: %q", t, s) -} - -// cmpTime compares two time.Times, returning -1 if the first is before the second, -// 1 if the first is after the second, and 0 if they're equal. -func cmpTime(a, b time.Time) int { - switch { - case a.Before(b): - return -1 - case a.After(b): - return 1 - default: - return 0 - } -} diff --git a/pmoupnp/devices/services/statevariables/utils_uint.go b/pmoupnp/devices/services/statevariables/utils_uint.go deleted file mode 100644 index 056a12f6..00000000 --- a/pmoupnp/devices/services/statevariables/utils_uint.go +++ /dev/null @@ -1,100 +0,0 @@ -package statevariables - -import ( - "errors" - "math" - "reflect" - "strconv" -) - -// maxUint returns maximum unsigned integer value for specified bit size -func maxUint(bits int) uint64 { - switch bits { - case 8: - return math.MaxUint8 - case 16: - return math.MaxUint16 - case 32: - return math.MaxUint32 - case 64: - return math.MaxUint64 - default: - return math.MaxUint64 // fallback - } -} - -// toUint converts various types of numeric values into a uint64 type. It -// supports conversions from signed and unsigned integers, floating-point -// numbers, and string representations of integers. -// -// Parameters: -// - v interface{}: input value that can be converted to uint64. The -// function will return an error if the input is not one of these types. -// - bits int: number of bits that should fit within the returned uint64. -// An error will be returned if the conversion would exceed this limit. -// -// Returns: -// - uint64: converted value from input 'v'. If the input 'v' is a string, -// it must represent an integer in base 10 and can fit into an uint64 -// type with given number of bits. -// - error: if the conversion fails due to unsupported input type, overflow -// or underflow conditions, or invalid string representation, this will -// contain an appropriate error message. If 'v' is nil, -// it returns an "cannot convert nil to uint" error. -func toUint(v interface{}, bits int) (uint64, error) { - if v == nil { - return 0, errors.New("cannot convert nil to uint") - } - - switch val := v.(type) { - case uint: - return checkUintBounds(uint64(val), bits) - case uint8: - return checkUintBounds(uint64(val), bits) - case uint16: - return checkUintBounds(uint64(val), bits) - case uint32: - return checkUintBounds(uint64(val), bits) - case uint64: - return checkUintBounds(val, bits) - - case int, int8, int16, int32, int64: - i := reflect.ValueOf(val).Int() - if i < 0 { - return 0, errors.New("negative value cannot be converted to uint") - } - return checkUintBounds(uint64(i), bits) - - case float32: - if val < 0 { - return 0, errors.New("negative float cannot be converted to uint") - } - return checkUintBounds(uint64(val), bits) - case float64: - if val < 0 { - return 0, errors.New("negative float cannot be converted to uint") - } - return checkUintBounds(uint64(val), bits) - - case string: - u, err := strconv.ParseUint(val, 10, bits) - if err != nil { - return 0, err - } - return checkUintBounds(u, bits) - - default: - return 0, errors.New("unsupported type for toUint") - } -} - -// checkUintBounds checks whether the given unsigned integer 'v' is within the -// acceptable range defined by the number of bits 'bits'. If 'v' is out of -// bounds, it returns an error with a message "unsigned integer value out of -// bounds". Otherwise, it returns 'v' and nil. -func checkUintBounds(v uint64, bits int) (uint64, error) { - if v > maxUint(bits) { - return 0, errors.New("unsigned integer value out of bounds") - } - return v, nil -} diff --git a/pmoupnp/devices/services/statevariables/utils_uri.go b/pmoupnp/devices/services/statevariables/utils_uri.go deleted file mode 100644 index 4f04876e..00000000 --- a/pmoupnp/devices/services/statevariables/utils_uri.go +++ /dev/null @@ -1,25 +0,0 @@ -package statevariables - -import ( - "fmt" - "net/url" -) - -// toURI converts a value to *url.URL if possible. -func toURI(v interface{}) (*url.URL, error) { - switch val := v.(type) { - case *url.URL: - // Already a URL - return val, nil - - case string: - u, err := url.Parse(val) - if err != nil { - return nil, fmt.Errorf("invalid URI string %q: %v", val, err) - } - return u, nil - - default: - return nil, fmt.Errorf("cannot convert type %T to URI", v) - } -} diff --git a/pmoupnp/devices/services/statevariables/utils_uuid.go b/pmoupnp/devices/services/statevariables/utils_uuid.go deleted file mode 100644 index 0a53a1a1..00000000 --- a/pmoupnp/devices/services/statevariables/utils_uuid.go +++ /dev/null @@ -1,32 +0,0 @@ -package statevariables - -import ( - "fmt" - - "github.com/google/uuid" -) - -// toUUID converts a value to uuid.UUID if possible. -func toUUID(v interface{}) (uuid.UUID, error) { - switch val := v.(type) { - case uuid.UUID: - return val, nil - - case string: - u, err := uuid.Parse(val) - if err != nil { - return uuid.UUID{}, fmt.Errorf("invalid UUID string %q: %v", val, err) - } - return u, nil - - case []byte: - u, err := uuid.FromBytes(val) - if err != nil { - return uuid.UUID{}, fmt.Errorf("invalid UUID bytes: %v", err) - } - return u, nil - - default: - return uuid.UUID{}, fmt.Errorf("cannot convert type %T to UUID", v) - } -} diff --git a/pmoupnp/devices/services/statevariables/valuerange.go b/pmoupnp/devices/services/statevariables/valuerange.go deleted file mode 100644 index a643dc3a..00000000 --- a/pmoupnp/devices/services/statevariables/valuerange.go +++ /dev/null @@ -1,61 +0,0 @@ -package statevariables - -import "fmt" - -// ValueRange represents an inclusive range constraint for a state variable value. -// It defines the minimum and maximum allowable values for a given UPnP type. -// -// Usage: -// - For numeric types: min/max must be numeric types -// - For time types: min/max must be time.Time values -// - For strings/UUIDs: min/max must be string values -// -// Use with StateVarType.InRange() to check if values fall within the range. -type ValueRange struct { - min interface{} - max interface{} -} - -// ValueRange creates a valid value range for the UPnP type. -// -// This method casts the provided min and max values to the UPnP type and returns -// a ValueRange struct suitable for range validation. If either value cannot be -// cast to the type, it returns an error. -// -// Parameters: -// -// min: Minimum value of the range (inclusive) -// max: Maximum value of the range (inclusive) -// -// Returns: -// -// ValueRange: Valid range structure if cast succeeds -// error: If min or max cannot be cast to the type -// -// Example: -// -// // Create a range for UI2 (uint16) values -// r, err := StateType_UI2.ValueRange(10, 100) -// if err != nil { /* handle error */ } -// valid := StateType_UI2.InRange(50, r) // true -// -// Notes: -// - The range is inclusive: [min, max] -// - Values must be comparable using the type's comparison logic -// - For time types, min and max must be valid time values -func (t StateVarType) ValueRange(min, max interface{}) (*ValueRange, error) { - cmin, error := t.Cast(min) - if error != nil { - return nil, fmt.Errorf("min value %v is not castable to type %s", min, t.String()) - } - cmax, error := t.Cast(max) - if error != nil { - return nil, fmt.Errorf("max value %v is not castable to type %s", min, t.String()) - } - - if cmp, err := t.Cmp(cmin, cmax); err != nil && cmp > 0 { - cmax, cmin = cmin, cmax - } - - return &ValueRange{min: cmin, max: cmax}, nil -} diff --git a/pmoupnp/events.go b/pmoupnp/events.go deleted file mode 100644 index 377fbfd1..00000000 --- a/pmoupnp/events.go +++ /dev/null @@ -1,5 +0,0 @@ -package pmoupnp - -import "github.com/beevik/etree" - -type UpnpEvent *etree.Element diff --git a/pmoupnp/interface.go b/pmoupnp/interface.go deleted file mode 100644 index 6aaac7a1..00000000 --- a/pmoupnp/interface.go +++ /dev/null @@ -1,5 +0,0 @@ -package pmoupnp - -type Markdownable interface { - ToMarkdown() string -} diff --git a/pmoupnp/objectstore/object.go b/pmoupnp/objectstore/object.go deleted file mode 100644 index 922067dd..00000000 --- a/pmoupnp/objectstore/object.go +++ /dev/null @@ -1,69 +0,0 @@ -package objectstore - -import ( - "iter" - - "github.com/google/uuid" - log "github.com/sirupsen/logrus" -) - -type ObjectIdSet map[uuid.UUID]struct{} - -func (set ObjectIdSet) Contains(id uuid.UUID) bool { - _, ok := set[id] - return ok -} - -func (set ObjectIdSet) Add(id uuid.UUID) { - set[id] = struct{}{} -} - -func (set ObjectIdSet) Remove(id uuid.UUID) { - delete(set, id) -} - -func (set ObjectIdSet) Clear() { - for k := range set { - delete(set, k) - } -} - -func (set ObjectIdSet) Len() int { - return len(set) -} - -func (set ObjectIdSet) All() iter.Seq[uuid.UUID] { - return func(yield func(uuid.UUID) bool) { - for uuid := range set { - if !yield(uuid) { - return - } - } - } -} - -var objectstore = make(map[uuid.UUID]Object) - -func RegisterObject(o Object) uuid.UUID { - id := uuid.New() - objectstore[id] = o - - return id -} - -func GetObject(id uuid.UUID) (Object, bool) { - o, ok := objectstore[id] - return o, ok -} - -func RemoveObject(id uuid.UUID) { - if _, ok := objectstore[id]; !ok { - delete(objectstore, id) - return - } - log.Warnf("Object %s not found in objectstore", id) -} - -func CountOfStoredObjects() int { - return len(objectstore) -} diff --git a/pmoupnp/objectstore/objectset.go b/pmoupnp/objectstore/objectset.go deleted file mode 100644 index 61e1530c..00000000 --- a/pmoupnp/objectstore/objectset.go +++ /dev/null @@ -1,40 +0,0 @@ -package objectstore - -import ( - "fmt" - "iter" -) - -type Object interface { - Name() string - TypeID() string -} - -type ObjectSet[T Object] map[string]T - -func (m *ObjectSet[T]) Insert(obj T) error { - if m.Contains(obj) { - return fmt.Errorf("object %s already present in set", obj.Name()) - } - (*m)[obj.Name()] = obj - return nil -} - -func (m *ObjectSet[T]) InsertOrReplace(obj T) { - (*m)[obj.Name()] = obj -} - -func (set *ObjectSet[T]) Contains(obj T) bool { - _, ok := (*set)[obj.Name()] - return ok -} - -func (m *ObjectSet[T]) All() iter.Seq[T] { - return func(yield func(T) bool) { - for _, sv := range *m { - if !yield(sv) { - return - } - } - } -} diff --git a/pmoupnp/server.go b/pmoupnp/server.go deleted file mode 100644 index 014e0cc2..00000000 --- a/pmoupnp/server.go +++ /dev/null @@ -1,204 +0,0 @@ -package pmoupnp - -import ( - "bytes" - "context" - "errors" - "fmt" - "net/http" - "runtime" - "sync" - "time" - - "github.com/beevik/etree" - log "github.com/sirupsen/logrus" - - "gargoton.petite-maison-orange.fr/eric/pmomusic/netutils" - "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoapp" - "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoconfig" - "gargoton.petite-maison-orange.fr/eric/pmomusic/pmocover" - "gargoton.petite-maison-orange.fr/eric/pmomusic/pmolog" - "gargoton.petite-maison-orange.fr/eric/pmomusic/ssdp" -) - -type Server struct { - name string - HTTPPort int - baseURL string - - Logger *log.Logger - httpSrv *http.Server - sspd *ssdp.SSDPServer - - devices DeviceInstanceSet - mu sync.RWMutex - startOnce sync.Once - stopOnce sync.Once -} - -func NewServer(name string, opts ...ServerOption) *Server { - config := pmoconfig.GetConfig() - - baseURL := config.GetBaseURL() - httpPort := config.GetHTTPPort() - - if baseURL == "" { - ip, err := netutils.GuessLocalIP() - if err != nil { - panic(fmt.Errorf("unable to determine local IP: %w", err)) - } - baseURL = fmt.Sprintf("http://%s:%d", ip, httpPort) - } - - s := &Server{ - name: name, - HTTPPort: httpPort, - baseURL: baseURL, - Logger: log.New(), - } - - for _, opt := range opts { - opt(s) - } - - return s -} - -func (s *Server) Name() string { return s.name } -func (s *Server) TypeID() string { return "Server" } - -type ServerOption func(*Server) - -func WithLogger(l *log.Logger) ServerOption { - return func(s *Server) { - s.Logger = l - } -} - -func (s *Server) Start() error { - s.startOnce.Do(func() { - mux := http.NewServeMux() - - s.mu.RLock() - - cover_cache, err := pmocover.GetCoverCache() - if err != nil { - log.Panicf("❌ Cannot initialize the Cover Cache") - } - - log.Info("✅ Cover cache activated") - - cover_cache.ServeMux(mux) - pmoapp.Handler(mux) - - s.httpSrv = &http.Server{ - Addr: fmt.Sprintf(":%d", s.HTTPPort), - Handler: mux, - } - - for device := range s.devices.All() { - err := device.RegisterURLs() - - if err != nil { - log.Panicf("❌ Cannot register URLs: %v", err) - } - } - - s.mu.RUnlock() - - go func() { - if err := s.httpSrv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { - s.Logger.Printf("❌ server error: %v", err) - } - }() - - log.Infof("✅ UPnP server started on %s", s.baseURL) - }) - - return nil -} - -func (s *Server) Stop(ctx context.Context) error { - var err error - s.stopOnce.Do(func() { - if s.httpSrv != nil { - s.Logger.Println("✅ Shutting down UPNP server...") - err = s.httpSrv.Shutdown(ctx) - } - }) - return err -} - -func (s *Server) Run(ctx context.Context) error { - if err := s.Start(); err != nil { - return fmt.Errorf("❌ failed to start server: %w", err) - } - - pmolog.LoggerWeb(ctx, s.httpSrv.Handler.(*http.ServeMux)) - - s.sspd = ssdp.NewSSDPServer() - if err := s.sspd.Start(ctx); err != nil { - return fmt.Errorf("❌ failed to start SSDP server: %w", err) - } - - for d := range s.devices.All() { - d.RegisterSSPD() - - for svc := range d.services.All() { - svc.StartNotifier(ctx, 1*time.Second) - } - } - - // attente d’annulation du contexte - <-ctx.Done() - - // arrêt avec le même ctx ou un nouveau ctx avec timeout - shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second) - defer cancel() - return s.Stop(shutdownCtx) -} - -func (s *Server) BaseURL() string { return s.baseURL } - -// ServeXML prend un générateur de XML (*etree.Element) -// et renvoie la string XML avec header. -func (s *Server) XML(gen func() *etree.Element) (string, error) { - root := gen() - doc := etree.NewDocument() - doc.SetRoot(root) - - doc.Indent(2) - - buf := new(bytes.Buffer) - if _, err := doc.WriteTo(buf); err != nil { - return "", err - } - - // Ajoute le header XML - return `` + "\n" + buf.String(), nil -} - -func (s *Server) ServeXML(gen func() *etree.Element) func(w http.ResponseWriter, r *http.Request) { - - return func(w http.ResponseWriter, r *http.Request) { - xmlStr, err := s.XML(gen) - if err != nil { - http.Error(w, "failed to generate XML", http.StatusInternalServerError) - return - } - - osName := runtime.GOOS - arch := runtime.GOARCH - - w.Header().Set("Server", fmt.Sprintf( - "%s/%s UPnP/1.1 PMOMusic/1.0", - osName, arch, - )) - w.Header().Set("Connection", "close") - w.Header().Set("Cache-Control", "max-age=1800") - w.Header().Set("EXT", "") - w.Header().Set("Content-Type", "text/xml; charset=\"utf-8\"") - w.WriteHeader(http.StatusOK) - w.Write([]byte(xmlStr)) - } -} diff --git a/pmoupnp/service.go b/pmoupnp/service.go deleted file mode 100644 index 9b67c148..00000000 --- a/pmoupnp/service.go +++ /dev/null @@ -1,99 +0,0 @@ -package pmoupnp - -import ( - "fmt" - "iter" - - "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/services/actions" - sv "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/services/statevariables" -) - -type Service struct { - name string - identifier string - version int - - actions actions.ActionSet - stateTable sv.StateVariableSet -} - -func NewService(name string) *Service { - svc := &Service{ - name: name, - identifier: name, - version: 1, - stateTable: make(sv.StateVariableSet), - actions: make(actions.ActionSet), - } - - return svc -} - -func (svc *Service) Name() string { - return svc.name -} - -func (svc *Service) TypeID() string { - return "Service" -} - -func (svc *Service) Identifier() string { - return svc.identifier -} - -func (svc *Service) SetIdentifier(id string) { - svc.identifier = id -} - -func (svc *Service) SetVersion(version int) error { - if version < 1 { - return fmt.Errorf("%s", "version must be greater than or equal to 1") - } - svc.version = version - return nil -} - -func (svc *Service) Version() int { - return svc.version -} - -func (svc *Service) AddVariable(sv *sv.StateVariable) error { - return svc.stateTable.Insert(sv) -} - -func (svc *Service) ContaintsVariable(sv *sv.StateVariable) bool { - return svc.stateTable.Contains(sv) -} - -func (svc *Service) Variables() iter.Seq[*sv.StateVariable] { - return svc.stateTable.All() -} - -func (svc *Service) AddAction(ac *actions.Action) error { - return svc.actions.Insert(ac) -} - -func (svc *Service) NewInstance() *ServiceInstance { - instance := &ServiceInstance{ - name: svc.Name(), - identifier: svc.Identifier(), - version: svc.Version(), - - statevariables: make(sv.StateVarInstanceSet), - actions: make(actions.ActionInstanceSet), - - subscribers: make(map[string]string), - changedBuffer: make(map[string]interface{}), - seqid: make(map[string]uint32), - } - - for v := range svc.stateTable.All() { - instance.statevariables.Insert(v.NewInstance()) - } - - for a := range svc.actions.All() { - instance.actions.Insert(a.NewInstance()) - } - - return instance -} diff --git a/pmoupnp/serviceinstance.go b/pmoupnp/serviceinstance.go deleted file mode 100644 index 1d230d38..00000000 --- a/pmoupnp/serviceinstance.go +++ /dev/null @@ -1,460 +0,0 @@ -package pmoupnp - -import ( - "context" - "fmt" - "io" - "net/http" - "net/url" - "strings" - "sync" - "time" - - "gargoton.petite-maison-orange.fr/eric/pmomusic/pmolog" - "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/services/actions" - "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/devices/services/statevariables" - "gargoton.petite-maison-orange.fr/eric/pmomusic/soap" - "github.com/beevik/etree" - "github.com/google/uuid" - log "github.com/sirupsen/logrus" -) - -type ServiceInstance struct { - name string - identifier string - version int - - device *DeviceInstance - statevariables statevariables.StateVarInstanceSet - actions actions.ActionInstanceSet - subscribers map[string]string // SID → Callback URL - changedBuffer map[string]interface{} - seqid map[string]uint32 - cbmu sync.Mutex - mu sync.Mutex -} - -const ( - MethodSubscribe = "SUBSCRIBE" - MethodUnsubscribe = "UNSUBSCRIBE" -) - -func (si *ServiceInstance) Name() string { - return si.name -} - -func (svc *ServiceInstance) TypeID() string { - return "ServiceInstance" -} - -func (si *ServiceInstance) Identifier() string { - return si.identifier -} - -func (svc *ServiceInstance) ServiceType() string { - return fmt.Sprintf("urn:schemas-upnp-org:service:%s:%d", svc.name, svc.version) -} - -func (svc *ServiceInstance) ServiceId() string { - return fmt.Sprintf("urn:upnp-org:serviceId:%s", svc.identifier) -} - -func (svc *ServiceInstance) BaseRoute() string { - return fmt.Sprintf("%s/service/%s", svc.device.BaseRoute(), svc.Name()) -} -func (svc *ServiceInstance) ControlURL() string { - return fmt.Sprintf("%s/control", svc.BaseRoute()) -} - -func (svc *ServiceInstance) EventSubURL() string { - return fmt.Sprintf("%s/event", svc.BaseRoute()) -} - -func (svc *ServiceInstance) SCPDURL() string { - return fmt.Sprintf("%s/desc.xml", svc.BaseRoute()) -} - -func (svc *ServiceInstance) RegisterURLs() error { - - mux, ok := svc.device.server.httpSrv.Handler.(*http.ServeMux) - - if mux == nil || !ok { - return fmt.Errorf("❌ Device %s the server handler is not correctly defined", svc.Name()) - } - - mux.HandleFunc( - svc.SCPDURL(), - svc.device.server.ServeXML(svc.SPCDElement), - ) - - mux.HandleFunc( - svc.ControlURL(), - svc.ControlHandler(), - ) - - mux.HandleFunc( - svc.EventSubURL(), - svc.EventSubHandler(), - ) - - log.Infof( - "✅ Service description for %s:%s available at : %s%s", - svc.device.Name(), - svc.Name(), - svc.device.server.BaseURL(), - svc.SCPDURL(), - ) - - return nil -} - -func (svc *ServiceInstance) USN() string { - return fmt.Sprintf("uuid:%s::urn:%s", svc.device.UDN(), svc.ServiceType()) -} - -func (svc *ServiceInstance) SPCDElement() *etree.Element { - elem := etree.NewElement("scpd") - - elem.CreateAttr("xmlns", "urn:schemas-upnp-org:service-1-0") - - spec := elem.CreateElement("specVersion") - spec.CreateElement("major").SetText("1") - spec.CreateElement("minor").SetText("0") - - if len(svc.actions) > 0 { - elem.AddChild(svc.actions.ToXMLElement()) - } - - if len(svc.statevariables) > 0 { - elem.AddChild(svc.statevariables.ToXMLElement()) - } - - return elem -} - -func (svc *ServiceInstance) AddSubscriber(sid, callback string) { - svc.mu.Lock() - defer svc.mu.Unlock() - if svc.subscribers == nil { - svc.subscribers = make(map[string]string) - } - svc.subscribers[sid] = callback -} - -func (svc *ServiceInstance) RenewSubscriber(sid, timeout string) { - // Pour l'instant juste log, on peut étendre avec expiration - svc.mu.Lock() - defer svc.mu.Unlock() - log.Infof("Renewed SID %s for timeout %s", sid, timeout) -} - -func (svc *ServiceInstance) RemoveSubscriber(sid string) { - svc.mu.Lock() - defer svc.mu.Unlock() - delete(svc.subscribers, sid) -} - -// Envoi d'un événement initial (optionnel) -func (svc *ServiceInstance) SendInitialEvent(sid string) { - svc.mu.Lock() - callback := svc.subscribers[sid] - svc.mu.Unlock() - if callback == "" { - return - } - - changed := make(map[string]interface{}) - for name, sv := range svc.statevariables { - if sv.IsSendingEvents() { // sendEvents="yes" - changed[name] = sv.Value() - } - } - - if len(changed) == 0 { - return - } - - go func() { - callback = strings.TrimSpace(callback) - callback = strings.Trim(callback, "<>") - - body := `` - for name, val := range changed { - body += fmt.Sprintf("<%s>%v", name, val, name) - } - body += "" - - req, _ := http.NewRequest("NOTIFY", callback, strings.NewReader(body)) - req.Header.Set("Content-Type", `text/xml; charset="utf-8"`) - req.Header.Set("NT", "upnp:event") - req.Header.Set("NTS", "upnp:propchange") - req.Header.Set("SID", sid) - req.Header.Set("SEQ", "0") // initial event - - client := &http.Client{} - resp, err := client.Do(req) - if err != nil { - log.Errorf("Failed to send initial event to %s: %v", callback, err) - return - } - defer resp.Body.Close() - log.Infof( - "✅ Initial event sent to %s, status=%s\n
\n\n```xml\n%s\n```\n
\n", - callback, - resp.Status, - pmolog.PrettyPrintXML(body), - ) - }() -} - -func (svc *ServiceInstance) ToXMLElement() *etree.Element { - elem := etree.NewElement("service") - - st := elem.CreateElement("serviceType") - st.SetText(svc.ServiceType()) - - sid := elem.CreateElement("serviceId") - sid.SetText(svc.ServiceId()) - - spcd := elem.CreateElement("SCPDURL") - spcd.SetText(svc.SCPDURL()) - - ctrl := elem.CreateElement("controlURL") - ctrl.SetText(svc.ControlURL()) - - event := elem.CreateElement("eventSubURL") - event.SetText(svc.EventSubURL()) - - return elem -} - -func (svc *ServiceInstance) EventToBeSent(name string, value interface{}) { - svc.cbmu.Lock() - defer svc.cbmu.Unlock() - - svc.changedBuffer[name] = value -} - -func (svc *ServiceInstance) nextSeq(sid string) string { - svc.mu.Lock() - defer svc.mu.Unlock() - - svc.seqid[sid]++ - return fmt.Sprintf("%d", svc.seqid[sid]) -} - -func (svc *ServiceInstance) NotifySubscribers() { - svc.cbmu.Lock() - if len(svc.subscribers) == 0 || len(svc.changedBuffer) == 0 { - svc.cbmu.Unlock() - return - } - - // Copier et réinitialiser le buffer - changed := svc.changedBuffer - svc.changedBuffer = make(map[string]interface{}) - svc.cbmu.Unlock() - - for sid, callback := range svc.subscribers { - go func(sid, callback string, changed map[string]interface{}) { - callback = strings.TrimSpace(callback) - callback = strings.Trim(callback, "<>") - - u, err := url.Parse(callback) - if err != nil { - log.Errorf("Invalid callback URL %s: %v", callback, err) - return - } - - body := `` - for name, val := range changed { - body += fmt.Sprintf("<%s>%v", name, val, name) - } - body += "" - - req, err := http.NewRequest("NOTIFY", u.String(), strings.NewReader(body)) - if err != nil { - log.Errorf("Failed to create NOTIFY request to %s: %v", callback, err) - return - } - - req.Header.Set("Content-Type", `text/xml; charset="utf-8"`) - req.Header.Set("NT", "upnp:event") - req.Header.Set("NTS", "upnp:propchange") - req.Header.Set("SID", sid) - req.Header.Set("SEQ", svc.nextSeq(sid)) - - client := &http.Client{} - resp, err := client.Do(req) - if err != nil { - log.Errorf("Failed to notify subscriber %s: %v", callback, err) - return - } - defer resp.Body.Close() - - log.Infof("✅ Notified subscriber %s of changes: %v", callback, changed) - }(sid, callback, changed) - } -} - -func (svc *ServiceInstance) StartNotifier(ctx context.Context, interval time.Duration) { - log.Infof("✅ Starting notifier for %s:%s every %.2f s", svc.device.Name(), svc.Name(), interval.Seconds()) - go func() { - ticker := time.NewTicker(interval) - defer ticker.Stop() - - for { - select { - case <-ctx.Done(): - log.Infof("✅ Notifier stopped for %s:%s", svc.device.Name(), svc.Name()) - return - case <-ticker.C: - svc.NotifySubscribers() - } - } - }() -} - -func (svc *ServiceInstance) EventSubHandler() func(w http.ResponseWriter, r *http.Request) { - return func(w http.ResponseWriter, r *http.Request) { - log.Infof("📡 Event Subscription request for %s:%s", svc.device.Name(), svc.Name()) - - sid := r.Header.Get("SID") - timeout := r.Header.Get("Timeout") - callback := r.Header.Get("Callback") - - switch r.Method { - case MethodSubscribe: - if sid == "" { - // Nouvelle subscription - sid = fmt.Sprintf("uuid:%s", uuid.New().String()) - if callback != "" { - svc.AddSubscriber(sid, callback) - } - if timeout == "" { - timeout = "Second-1800" - } - log.Infof("🔔 New subscription: SID=%s, Callback=%s, Timeout=%s", sid, callback, timeout) - go svc.SendInitialEvent(sid) // envoyer l’état initial - } else { - // Renouvellement - svc.RenewSubscriber(sid, timeout) - log.Infof("♻️ Renew subscription: SID=%s, Timeout=%s", sid, timeout) - } - - w.Header().Set("SID", sid) - w.Header().Set("Timeout", timeout) - w.WriteHeader(http.StatusOK) - - case MethodUnsubscribe: - if sid != "" { - svc.RemoveSubscriber(sid) - log.Infof("❌ Unsubscribe SID=%s", sid) - } - w.WriteHeader(http.StatusOK) - - default: - log.Warnf("Unsupported EventSub method: %s", r.Method) - http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed) - } - - // Debug log headers - for k, v := range r.Header { - log.Debugf("Header: %s=%v", k, v) - } - - // Lire le body au besoin - body, err := io.ReadAll(r.Body) - if err == nil && len(body) > 0 { - log.Debugf("Body: %s", string(body)) - } - } -} - -func (svc *ServiceInstance) ControlHandler() func(w http.ResponseWriter, r *http.Request) { - return func(w http.ResponseWriter, r *http.Request) { - log.Infof("📡 Control request for %s:%s", svc.device.Name(), svc.Name()) - - body, err := io.ReadAll(r.Body) - if err != nil { - log.Errorf("❌ Failed to read body: %v", err) - http.Error(w, "bad request", http.StatusBadRequest) - return - } - - // Callback générique pour décoder chaque paramètre - decoder := func(action, param, value string) (string, interface{}, error) { - // 1️⃣ Chercher si le param correspond à une StateVarInstance - - sv, ok := svc.statevariables[param] - log.Debugf("Look for a variable named : %s -> %v", param, ok) - - if ok { - if sv.HasParser() { - v, err := sv.ParseValue(value) - if err != nil { - return param, value, err - } - return param, v, err - } - v, err := sv.Cast(value) - if err != nil { - return param, value, err - } - return param, v, nil - } - - // 2️⃣ Chercher si le param correspond à une ActionInstance et appliquer un parseur associé - act, ok := svc.actions[action] - log.Debugf("Look for an action named : %s -> %v", action, ok) - - if ok { - if argument, ok := act.Arguments(param); ok { - sv_name := argument.StateVariable().Name() - sv := svc.statevariables[sv_name] - v, err := sv.ParseValue(value) - - log.Debugf("It corresponds to variable : %s with a parser %v", sv_name, sv.HasParser()) - - if err != nil { - return param, value, err - } - return param, v, nil - } - } - - // 3️⃣ Sinon, valeur brute - return param, value, nil - } - - env, err := soap.ParseSOAPEnvelope(body) - - if err != nil { - log.Errorf("❌ Failed to parse SOAP enveloppe: %v", err) - soapResp, _ := soap.BuildSOAPFault("s:Client", "Invalid Args", err.Error()) - w.Header().Set("Content-Type", `text/xml; charset="utf-8"`) - w.WriteHeader(http.StatusInternalServerError) - _, _ = w.Write(soapResp) - return - } - - req, err := soap.ParseUPnPAction(env, decoder) - if err != nil { - log.Errorf("❌ Failed to parse SOAP Action: %v", err) - soapResp, _ := soap.BuildSOAPFault("s:Client", "Invalid Args", err.Error()) - w.Header().Set("Content-Type", `text/xml; charset="utf-8"`) - w.WriteHeader(http.StatusInternalServerError) - _, _ = w.Write(soapResp) - return - } - - log.Info(req.ToMarkdown()) - - // Ici tu peux appeler l'action correspondante sur svc.actions[req.Name] et récupérer le résultat - // Exemple de réponse minimale : - resp, _ := soap.BuildUPnPResponse(svc.ServiceType(), req.Name, map[string]string{}) - w.Header().Set("Content-Type", `text/xml; charset="utf-8"`) - w.WriteHeader(http.StatusOK) - _, _ = w.Write(resp) - } -} diff --git a/pmoupnp/serviceinstanceset.go b/pmoupnp/serviceinstanceset.go deleted file mode 100644 index 0086d4d4..00000000 --- a/pmoupnp/serviceinstanceset.go +++ /dev/null @@ -1,36 +0,0 @@ -package pmoupnp - -import ( - "iter" - - "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/objectstore" - "github.com/beevik/etree" -) - -type ServiceInstanceSet objectstore.ObjectSet[*ServiceInstance] - -func (m *ServiceInstanceSet) Insert(obj *ServiceInstance) error { - return (*objectstore.ObjectSet[*ServiceInstance])(m).Insert(obj) -} - -func (m *ServiceInstanceSet) InsertOrReplace(obj *ServiceInstance) { - (*objectstore.ObjectSet[*ServiceInstance])(m).InsertOrReplace(obj) -} - -func (set *ServiceInstanceSet) Contains(obj *ServiceInstance) bool { - return (*objectstore.ObjectSet[*ServiceInstance])(set).Contains(obj) -} - -func (m *ServiceInstanceSet) All() iter.Seq[*ServiceInstance] { - return (*objectstore.ObjectSet[*ServiceInstance])(m).All() -} - -func (m *ServiceInstanceSet) ToXMLElement() *etree.Element { - elem := etree.NewElement("serviceList") - - for sv := range m.All() { - elem.AddChild(sv.ToXMLElement()) - } - - return elem -} diff --git a/pmoupnp/serviceset.go b/pmoupnp/serviceset.go deleted file mode 100644 index c70a4d59..00000000 --- a/pmoupnp/serviceset.go +++ /dev/null @@ -1,25 +0,0 @@ -package pmoupnp - -import ( - "iter" - - "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoupnp/objectstore" -) - -type ServiceSet objectstore.ObjectSet[*Service] - -func (m *ServiceSet) Insert(obj *Service) error { - return (*objectstore.ObjectSet[*Service])(m).Insert(obj) -} - -func (m *ServiceSet) InsertOrReplace(obj *Service) { - (*objectstore.ObjectSet[*Service])(m).InsertOrReplace(obj) -} - -func (set *ServiceSet) Contains(obj *Service) bool { - return (*objectstore.ObjectSet[*Service])(set).Contains(obj) -} - -func (m *ServiceSet) All() iter.Seq[*Service] { - return (*objectstore.ObjectSet[*Service])(m).All() -} diff --git a/pmoupnp/srv_reg_devices.go b/pmoupnp/srv_reg_devices.go deleted file mode 100644 index 20661835..00000000 --- a/pmoupnp/srv_reg_devices.go +++ /dev/null @@ -1,44 +0,0 @@ -package pmoupnp - -import ( - "gargoton.petite-maison-orange.fr/eric/pmomusic/pmoconfig" - log "github.com/sirupsen/logrus" -) - -func (s *Server) RegisterDevice(name string, d *Device) { - s.mu.Lock() - defer s.mu.Unlock() - - if s.devices == nil { - s.devices = make(DeviceInstanceSet) - } - - if name == "" { - name = d.Name() - } - - config := pmoconfig.GetConfig() - udn := config.GetDeviceUDN(string(d.DeviceType()), name) - - instance := d.NewInstance(s, udn) - - log.Infof("✅ Registering device %s", name) - - err := s.devices.Insert(instance) - - if err != nil { - log.Panicf("❌ Device %s is already registered", instance.Name()) - } - - log.Infof("✅ New device %s get UDN : %s", instance.Name(), instance.UDN()) - - // s.devices[name] = d - // d.mu.Lock() - // defer d.mu.Unlock() - // d.UDN = s.UDN + "-" + name - // d.Name = name - - // for _, service := range d.Services.All() { - // service.DeviceName = name - // } -} diff --git a/soap/buildsoap.go b/soap/buildsoap.go deleted file mode 100644 index 18b78f3e..00000000 --- a/soap/buildsoap.go +++ /dev/null @@ -1,89 +0,0 @@ -package soap - -import ( - "bytes" - "encoding/xml" - "fmt" -) - -// ----- Générateurs ----- - -// BuildUPnPResponse construit une réponse SOAP avec -func BuildUPnPResponse(serviceURN, action string, values map[string]string) ([]byte, error) { - env := &Envelope{ - XMLName: xml.Name{Local: "s:Envelope"}, - Body: Body{ - Content: buildActionResponse(serviceURN, action, values), - }, - } - - return marshalSOAP(env) -} - -// BuildSOAPFault construit un Fault SOAP standard -func BuildSOAPFault(code, description, detail string) ([]byte, error) { - env := &Envelope{ - XMLName: xml.Name{Local: "s:Envelope"}, - Body: Body{ - Content: buildFault(code, description, detail), - }, - } - - return marshalSOAP(env) -} - -// ----- Internes ----- - -func buildActionResponse(serviceURN, action string, values map[string]string) []byte { - var buf bytes.Buffer - buf.WriteString(fmt.Sprintf(``, action, serviceURN)) - for k, v := range values { - buf.WriteString(fmt.Sprintf("<%s>%s", k, xmlEscape(v), k)) - } - buf.WriteString(fmt.Sprintf(``, action)) - return buf.Bytes() -} - -func buildFault(code, description, detail string) []byte { - return []byte(fmt.Sprintf(` - - %s - %s - %s -`, xmlEscape(code), xmlEscape(description), xmlEscape(detail))) -} - -func marshalSOAP(env *Envelope) ([]byte, error) { - type soapEnvelope struct { - XMLName xml.Name `xml:"s:Envelope"` - SoapNS string `xml:"xmlns:s,attr"` - EncNS string `xml:"s:encodingStyle,attr"` - Body struct { - XMLName xml.Name `xml:"s:Body"` - Content string `xml:",innerxml"` - } - } - - tmp := soapEnvelope{ - SoapNS: "http://schemas.xmlsoap.org/soap/envelope/", - EncNS: "http://schemas.xmlsoap.org/soap/encoding/", - } - tmp.Body.Content = string(env.Body.Content) - - var buf bytes.Buffer - buf.WriteString(``) - enc := xml.NewEncoder(&buf) - enc.Indent("", " ") - if err := enc.Encode(tmp); err != nil { - return nil, err - } - enc.Flush() - return buf.Bytes(), nil -} - -// xmlEscape échappe manuellement les caractères dangereux -func xmlEscape(s string) string { - var buf bytes.Buffer - xml.EscapeText(&buf, []byte(s)) - return buf.String() -} diff --git a/soap/markdown.go b/soap/markdown.go deleted file mode 100644 index 4278cf20..00000000 --- a/soap/markdown.go +++ /dev/null @@ -1,69 +0,0 @@ -package soap - -import ( - "bytes" - "fmt" - "strings" -) - -// Markdownable représente un objet pouvant se transformer en Markdown -type Markdownable interface { - ToMarkdown() string -} - -// ToMarkdown convertit l'action et ses arguments en Markdown lisible -func (ar *ActionRequest) ToMarkdown() string { - var buf bytes.Buffer - - // Titre de l'action - buf.WriteString(fmt.Sprintf("➡️ SOAP Action: %s\n\n", ar.Name)) - - for key, val := range ar.Args { - buf.WriteString(fmt.Sprintf("- **%s**: ", key)) - - var content string - if md, ok := val.(Markdownable); ok { - content = md.ToMarkdown() - } else { - content = fmt.Sprintf("%v", val) - } - - // Si contenu long ou multi-lignes - if strings.Contains(content, "\n") || len(content) > 60 { - // Résumé : première ligne ou URL tronquée - summary := firstLineOrTruncate(content, 60) - buf.WriteString(fmt.Sprintf("`%s`\n", summary)) - buf.WriteString("
\n\n") - - // Conserver Markdown complet, sans indentation - buf.WriteString(content) - if !strings.HasSuffix(content, "\n") { - buf.WriteString("\n") - } - buf.WriteString("
\n\n") - } else if isURL(content) { - buf.WriteString(fmt.Sprintf("[%s](%s)\n", content, content)) - } else { - buf.WriteString(fmt.Sprintf("`%s`\n", content)) - } - } - - return buf.String() -} - -// Tronque la première ligne ou l'URL si trop longue -func firstLineOrTruncate(s string, max int) string { - lines := strings.SplitN(s, "\n", 2) - first := lines[0] - if len(first) > max { - return first[:max] + "…" - } - - first = strings.TrimLeft(first, "# ") - return first -} - -// Vérifie si une string ressemble à une URL -func isURL(s string) bool { - return strings.HasPrefix(s, "http://") || strings.HasPrefix(s, "https://") -} diff --git a/soap/parseSoap.go b/soap/parseSoap.go deleted file mode 100644 index 66b4fc6b..00000000 --- a/soap/parseSoap.go +++ /dev/null @@ -1,195 +0,0 @@ -package soap - -import ( - "bytes" - "encoding/xml" - "fmt" - "io" - - log "github.com/sirupsen/logrus" -) - -// ----- SOAP envelope ----- - -type Envelope struct { - XMLName xml.Name `xml:"http://schemas.xmlsoap.org/soap/envelope/ Envelope"` - Header *Header `xml:"Header"` - Body Body `xml:"Body"` -} - -type Header struct { - Content []byte `xml:",innerxml"` -} - -type Body struct { - Content []byte `xml:",innerxml"` -} - -// ----- UPnP request/response ----- - -type ActionRequest struct { - Name string - Args map[string]interface{} - RawXML []byte -} - -type ActionResponse struct { - Name string - Values map[string]string - RawXML []byte -} - -type Fault struct { - Code string - Description string - Detail string - RawXML []byte -} - -// ----- Utils ----- - -// ----- Parseurs ----- - -func ParseSOAPEnvelope(body []byte) (*Envelope, error) { - var env Envelope - if err := xml.Unmarshal(body, &env); err != nil { - return nil, fmt.Errorf("unmarshal SOAP Envelope: %w", err) - } - return &env, nil -} - -// ParamDecoder permet de transformer les valeurs des paramètres et éventuellement renommer le paramètre -type ParamDecoder func(action, param, value string) (newParam string, out interface{}, err error) - -// ParseUPnPAction extrait l’action et ses arguments à partir d’un Body SOAP. -// Si decoder != nil, il est appelé pour chaque paramètre. -func ParseUPnPAction(env *Envelope, decoder ParamDecoder) (*ActionRequest, error) { - dec := xml.NewDecoder(bytes.NewReader(env.Body.Content)) - var currentAction string - args := make(map[string]interface{}) - - for { - tok, err := dec.Token() - if err != nil { - if err == io.EOF { - break - } - return nil, fmt.Errorf("SOAP parse error: %w", err) - } - - switch t := tok.(type) { - case xml.StartElement: - if currentAction == "" { - currentAction = t.Name.Local - } else { - var value string - if err := dec.DecodeElement(&value, &t); err != nil { - return nil, fmt.Errorf("decode param %s: %w", t.Name.Local, err) - } - - paramName := t.Name.Local - var paramValue interface{} = value - - if decoder != nil { - if newName, out, err := decoder(currentAction, paramName, value); err == nil { - paramName = newName - paramValue = out - } - } - - args[paramName] = paramValue - } - } - } - - return &ActionRequest{ - Name: currentAction, - Args: args, - RawXML: env.Body.Content, - }, nil -} - -// Response (renderer -> contrôleur) -func ParseUPnPResponse(env *Envelope) (*ActionResponse, *Fault, error) { - dec := xml.NewDecoder(bytes.NewReader(env.Body.Content)) - var respName string - values := make(map[string]string) - - for { - tok, err := dec.Token() - if err != nil { - if err == io.EOF { - break - } - return nil, nil, fmt.Errorf("SOAP parse error: %w", err) - } - - switch t := tok.(type) { - case xml.StartElement: - if t.Name.Local == "Fault" { - // Parse fautes SOAP - var f struct { - Code string `xml:"faultcode"` - Desc string `xml:"faultstring"` - Detail string `xml:"detail"` - } - if err := dec.DecodeElement(&f, &t); err != nil { - return nil, nil, fmt.Errorf("decode Fault: %w", err) - } - return nil, &Fault{ - Code: f.Code, - Description: f.Desc, - Detail: f.Detail, - RawXML: env.Body.Content, - }, nil - } - - if respName == "" { - respName = t.Name.Local - } else { - var value string - if err := dec.DecodeElement(&value, &t); err != nil { - return nil, nil, fmt.Errorf("decode response param %s: %w", t.Name.Local, err) - } - values[t.Name.Local] = value - } - } - } - - if respName == "" { - return nil, nil, fmt.Errorf("no response or fault in SOAP body") - } - - return &ActionResponse{respName, values, env.Body.Content}, nil, nil -} - -// ----- Exemple ----- - -func ParseSOAPGeneric(body []byte, decoder ParamDecoder) { - env, err := ParseSOAPEnvelope(body) - if err != nil { - log.Warnf("❌ %v", err) - return - } - - // Essayer d'abord comme requête - if req, err := ParseUPnPAction(env, decoder); err == nil && req.Name != "" { - log.Infof("📡 SOAP Request Action: %s", req.Name) - for k, v := range req.Args { - log.Infof(" %s = %v", k, v) - } - return - } - - // Sinon comme réponse - if resp, fault, err := ParseUPnPResponse(env); err == nil { - if resp != nil { - log.Infof("📡 SOAP Response: %s", resp.Name) - for k, v := range resp.Values { - log.Infof(" %s = %v", k, v) - } - } else if fault != nil { - log.Warnf("❌ SOAP Fault: %s - %s (detail: %s)", fault.Code, fault.Description, fault.Detail) - } - } -} diff --git a/ssdp/server.go b/ssdp/server.go deleted file mode 100644 index 4af0262f..00000000 --- a/ssdp/server.go +++ /dev/null @@ -1,243 +0,0 @@ -package ssdp - -import ( - "bufio" - "context" - "fmt" - "net" - "slices" - "strings" - "sync" - "time" - - log "github.com/sirupsen/logrus" -) - -const ( - SsdpAddr = "239.255.255.250" - Port = 1900 - MaxAge = 1800 -) - -type Device struct { - UUID string - DeviceType string - Location string - Server string - NTs []string -} - -// GetNTs retourne la liste des NT à annoncer pour ce périphérique -func (d *Device) GetNTs() []string { - return d.NTs -} - -type SSDPServer struct { - Devices map[string]*Device - mu sync.RWMutex - conn *net.UDPConn -} - -// NewSSDPServer crée un serveur SSDP -func NewSSDPServer() *SSDPServer { - return &SSDPServer{ - Devices: make(map[string]*Device), - } -} - -// AddDevice ajoute un périphérique et envoie un alive initial -func (s *SSDPServer) AddDevice(d *Device) { - s.mu.Lock() - defer s.mu.Unlock() - - s.Devices[d.UUID] = d - for _, nt := range d.GetNTs() { - s.SendAlive(d.UUID, nt, d.Location, d.Server) - } -} - -// RemoveDevice supprime un périphérique et envoie un byebye -func (s *SSDPServer) RemoveDevice(uuid string) { - s.mu.Lock() - defer s.mu.Unlock() - - d, ok := s.Devices[uuid] - if !ok { - return - } - for _, nt := range d.GetNTs() { - s.SendByeBye(d.UUID, nt) - } - delete(s.Devices, uuid) -} - -// Start démarre l'écoute SSDP et envoie les alive périodiques -func (s *SSDPServer) Start(ctx context.Context) error { - addr := &net.UDPAddr{IP: net.ParseIP(SsdpAddr), Port: Port} - log.Infof("✅ Starting SSDP listener") - conn, err := net.ListenMulticastUDP("udp4", nil, addr) - if err != nil { - return err - } - conn.SetReadBuffer(8192) - s.conn = conn - - // Alive périodique - go func() { - ticker := time.NewTicker(time.Duration(MaxAge/2) * time.Second) - defer ticker.Stop() - for { - select { - case <-ctx.Done(): - return - case <-ticker.C: - s.mu.RLock() - for _, d := range s.Devices { - for _, nt := range d.GetNTs() { - s.SendAlive(d.UUID, nt, d.Location, d.Server) - } - } - s.mu.RUnlock() - } - } - }() - - // Écoute des M-SEARCH - go func() { - buf := make([]byte, 8192) - for { - select { - case <-ctx.Done(): - log.Infof("✅ Stopping SSDP listener, sending byebye for all devices") - s.mu.RLock() - for _, d := range s.Devices { - for _, nt := range d.GetNTs() { - s.SendByeBye(d.UUID, nt) - } - } - s.mu.RUnlock() - conn.Close() - return - default: - conn.SetReadDeadline(time.Now().Add(1 * time.Second)) - n, src, err := conn.ReadFromUDP(buf) - if err != nil { - if ne, ok := err.(net.Error); ok && ne.Timeout() { - continue - } - log.Warnf("❌ SSDP read error: %v", err) - continue - } - data := string(buf[:n]) - if strings.HasPrefix(data, "M-SEARCH") { - s.mu.RLock() - for _, d := range s.Devices { - s.handleMSearch(src, data, d) - } - s.mu.RUnlock() - } - } - } - }() - return nil -} - -// SendSSDP envoie un NOTIFY multicast -func (s *SSDPServer) SendSSDP(msg string) error { - addr := &net.UDPAddr{IP: net.ParseIP(SsdpAddr), Port: Port} - _, err := s.conn.WriteToUDP([]byte(msg), addr) - return err -} - -// SendAlive envoie un NOTIFY ssdp:alive -func (s *SSDPServer) SendAlive(usn, nt, location, server string) { - msg := fmt.Sprintf(`NOTIFY * HTTP/1.1 -HOST: %s:%d -CACHE-CONTROL: max-age=%d -LOCATION: %s -NT: %s -NTS: ssdp:alive -SERVER: %s -USN: uuid:%s::%s - -`, SsdpAddr, Port, MaxAge, location, nt, server, usn, nt) - - if err := s.SendSSDP(msg); err != nil { - log.Warnf("❌ Failed to notify alive: USN %s: %v", usn, err) - } else { - log.Infof("✅ Notify alive: USN %s (NT=%s)", usn, nt) - } -} - -// SendByeBye envoie un NOTIFY ssdp:byebye -func (s *SSDPServer) SendByeBye(usn, nt string) { - msg := fmt.Sprintf(`NOTIFY * HTTP/1.1 -HOST: %s:%d -NT: %s -NTS: ssdp:byebye -USN: uuid:%s::%s - -`, SsdpAddr, Port, nt, usn, nt) - msg = strings.ReplaceAll(msg, "\n", "\r\n") - - if err := s.SendSSDP(msg); err != nil { - log.Warnf("❌ Failed to notify byebye: USN %s: %v", usn, err) - } else { - log.Infof("👋 Notify byebye: USN %s (NT=%s)", usn, nt) - } -} - -// handleMSearch répond à un M-SEARCH en unicast -func (s *SSDPServer) handleMSearch(src *net.UDPAddr, req string, d *Device) { - st := parseST(req) - if st == "" { - return - } - - valid := st == "ssdp:all" || - slices.Contains(d.GetNTs(), st) - - if !valid { - return - } - - log.Infof("M-Search response on a valid ST: %s", st) - nts := []string{st} - if st == "ssdp:all" { - nts = d.GetNTs() - } - - nts = d.GetNTs() - for _, st := range nts { - resp := fmt.Sprintf(`HTTP/1.1 200 OK -CACHE-CONTROL: max-age=%d -DATE: %s -EXT: -LOCATION: %s -SERVER: %s -ST: %s -USN: uuid:%s::%s - -`, MaxAge, time.Now().UTC().Format(time.RFC1123), d.Location, d.Server, st, d.UUID, st) - resp = strings.ReplaceAll(resp, "\n", "\r\n") - if _, err := s.conn.WriteToUDP([]byte(resp), src); err != nil { - log.Warnf("❌ Failed to send M-SEARCH response to %v: %v", src, err) - } else { - log.Infof("📡 Responded to M-SEARCH from %v with ST=%s\n
\n\n```\n%s\n```\n
\n\n", src, st, resp) - } - } -} - -// parseST extrait le ST d’un M-SEARCH -func parseST(req string) string { - scanner := bufio.NewScanner(strings.NewReader(req)) - for scanner.Scan() { - line := scanner.Text() - if strings.HasPrefix(strings.ToUpper(line), "ST:") { - st := strings.TrimSpace(line[3:]) - log.Infof("✅ Found ST=%s in M-SEARCH response", st) - return st - } - } - return "" -} diff --git a/xx b/xx deleted file mode 100644 index 787c3dac..00000000 --- a/xx +++ /dev/null @@ -1,806 +0,0 @@ -------- /pmoupnp/devices/services/statevariables/statevartype_arithm.go ------ -package statevariables - -// Add performs addition operation on two interfaces if both are of numeric -// type, otherwise it returns an error. If the types are not numeric, it checks -// and converts them into float64 before performing the addition. The function -// then casts the result back to its original type using Cast method from -// StateVarType t and returns this value or any encountered error. -// -// Parameters: -// -// a (interface{}): First operand for addition operation. Can be of any type. -// b (interface{}): Second operand for addition operation. Can be of any type. -// -// Returns: -// -// interface{}: Result of the addition, casted back to its original type using StateVarType t if no error encountered. -// error: Encountered error in case any conversion or casting fails. This includes non-numeric types for this operation. -func (t StateVarType) Add(a, b interface{}) (interface{}, error) { - af, bf, err := valuesToNumericOperands(t, a, b) - if err != nil { - return nil, err - } - - return t.Cast(af + bf) -} - -// Sub subtracts 'b' from 'a'. It converts both values to numeric types -// and then performs a subtraction operation, casting the result back to its -// original type. If either conversion fails or an unsupported type is used, -// it returns an error. -func (t StateVarType) Sub(a, b interface{}) (interface{}, error) { - af, bf, err := valuesToNumericOperands(t, a, b) - if err != nil { - return nil, err - } - - return t.Cast(af - bf) -} - -// Mul takes in two interface types 'a' and 'b', multiplies them together -// and returns the result along with any error encountered during this -// process. If either of the inputs is not compatible with numeric values, an -// error will be returned. The multiplication operation is performed between two -// numbers represented as 'float64' types (since Go does not support generic -// types on its own). The resulting value will be cast to the type represented -// by the receiver of this method 't'. If a casting error occurs, it will also -// be returned along with nil for the result. -func (t StateVarType) Mul(a, b interface{}) (interface{}, error) { - af, bf, err := valuesToNumericOperands(t, a, b) - if err != nil { - return nil, err - } - - return t.Cast(af * bf) -} - -// Div performs division between the provided arguments 'a' and 'b'. The function casts both operands to their numeric equivalents using valuesToNumericOperands() before performing the division. -// -// Parameters: -// - a: first operand of type interface{}, can be of any type, will be converted if necessary -// - b: second operand of type interface{}, can be of any type, will be converted if necessary -// -// Returns: -// - result: the division result in numeric form after casting it with function t.Cast() -// - err: error that might occur during the conversion or division operation -func (t StateVarType) Div(a, b interface{}) (interface{}, error) { - af, bf, err := valuesToNumericOperands(t, a, b) - if err != nil { - return nil, err - } - - return t.Cast(af / bf) -} ------------------ -------- /pmoupnp/devices/services/statevariables/statevartype_cast.go ------ -package statevariables - -import ( - "fmt" - "net/url" - "strings" - "time" - - "github.com/google/uuid" -) - -// Cast converts a value to the Go type corresponding to the UPnP type. -// Supports conversion from various primitive types and strings. -// Returns an error for unsupported conversions or invalid values. -// -// Examples: -// - StateType_UI2.Cast(42) // uint16(42), nil -// - StateType_Boolean.Cast("true") // true, nil -// - StateType_UI1.Cast(300) // nil, error (overflow) -func (t StateVarType) Cast(val interface{}) (interface{}, error) { - switch t { - case StateType_UI1: - v, err := toUint(val, 8) - if err != nil { - return nil, fmt.Errorf("cannot cast %v (%T) to UI1", val, val) - } - return uint8(v), nil - - case StateType_UI2: - v, err := toUint(val, 16) - if err != nil { - return nil, fmt.Errorf("cannot cast %v (%T) to UI2", val, val) - } - return uint16(v), nil - - case StateType_UI4: - v, err := toUint(val, 32) - if err != nil { - return nil, fmt.Errorf("cannot cast %v (%T) to UI4", val, val) - } - return uint32(v), nil - - case StateType_I1: - v, err := toInt(val, 8) - if err != nil { - return nil, fmt.Errorf("cannot cast %v (%T) to I1", val, val) - } - return int8(v), nil - - case StateType_I2: - v, err := toInt(val, 16) - if err != nil { - return nil, fmt.Errorf("cannot cast %v (%T) to I2", val, val) - } - return int16(v), nil - - case StateType_I4, StateType_Int: - v, err := toInt(val, 32) - if err != nil { - return nil, fmt.Errorf("cannot cast %v (%T) to I4", val, val) - } - return int32(v), nil - - case StateType_R4: - v, err := toFloat(val, 32) - if err != nil { - return nil, fmt.Errorf("cannot cast %v (%T) to R4", val, val) - } - return float32(v), nil - - case StateType_R8, StateType_Number, StateType_Fixed14_4: - v, err := toFloat(val, 64) - if err != nil { - return nil, fmt.Errorf("cannot cast %v (%T) to R8", val, val) - } - return v, nil - - case StateType_Boolean: - b, err := toBool(val) - if err != nil { - return nil, fmt.Errorf("cannot cast %v (%T) to Boolean", val, val) - } - return b, nil - - case StateType_Char: - switch s := val.(type) { - case string: - if len(s) != 1 { - return nil, fmt.Errorf("invalid Char: string too long %q", s) - } - return rune(s[0]), nil - case rune: - return s, nil - default: - return nil, fmt.Errorf("cannot cast %v (%T) to Char", val, val) - } - - case StateType_String: - return fmt.Sprint(val), nil - - case StateType_UUID: - switch val := val.(type) { - case uuid.UUID: - return val, nil - case string: - u, err := uuid.Parse(strings.TrimSpace(val)) - if err != nil { - return nil, fmt.Errorf("invalid UUID %v: %v", val, err) - } - return u, nil - default: - return nil, fmt.Errorf("cannot cast %v (%T) to UUID", val, val) - } - - case StateType_URI: - switch val := val.(type) { - case *url.URL: - return val, nil - case string: - u, err := url.Parse(strings.TrimSpace(val)) - if err != nil { - return nil, fmt.Errorf("invalid URI %v: %v", val, err) - } - return u, nil - default: - return nil, fmt.Errorf("cannot cast %v (%T) to URI", val, val) - } - - case StateType_BinBase64, StateType_BinHex: - switch v := val.(type) { - case []byte: - return v, nil - case string: - return decodeBinary(t, v) - default: - return nil, fmt.Errorf("cannot cast %v (%T) to binary", val, val) - } - - case StateType_Date, StateType_DateTime, StateType_DateTimeTZ, - StateType_Time, StateType_TimeTZ: - switch v := val.(type) { - case time.Time: - return v, nil - case string: - return parseUPnPTime(t, v) - default: - return nil, fmt.Errorf("cannot cast %v (%T) to time", val, val) - } - - default: - return nil, fmt.Errorf("unsupported type: %v", t) - } -} ------------------ -------- /pmoupnp/devices/services/statevariables/statevartype_cmp.go ------ -package statevariables - -import ( - "bytes" - "fmt" - "log" - "strings" -) - -// Cmp compares two values of a given type 'StateVarType'. The comparison is -// made based on the specific type of 'a' and 'b'. It returns an integer -// indicating whether 'a' is less than, equal to, or greater than 'b'. If 'a' is -// less than 'b', it returns -1. If they are equal, it returns 0. If 'a' is -// greater than 'b', it returns 1. It also returns an error if any of the values -// can't be cast to the required type or if comparison isn't supported for the -// given type 'StateVarType'. -// -// - t: StateVarType representing the specific type to use for comparison. -// - a, b: The values to compare. They should be of type interface{} as they could be -// any valid Go type. -// -// Returns: An integer indicating the result of the comparison (-1 if 'a' is -// less than 'b', 0 if they are equal, and 1 if 'a' is greater than 'b'). It -// also returns an error if any values can't be cast or if comparison isn't -// supported for the given type. -// -// Example: -// -// result, err := t.Cmp(int32(5), int32(7)) // Returns -1 and nil error as 5 is less than 7. -func (t StateVarType) Cmp(a, b interface{}) (int, error) { - a, err1 := t.Cast(a) - b, err2 := t.Cast(b) - - if err1 != nil || err2 != nil { - log.Fatalf("Failed to cast for comparison: %v vs %v (errors: %v, %v)", a, b, err1, err2) - } - - switch { - case t.IsInteger(): - ai, err := toInt(a, t.BitSize()) - if err != nil { - return 0, fmt.Errorf("invalid int value for a: %w", err) - } - bi, err := toInt(b, t.BitSize()) - if err != nil { - return 0, fmt.Errorf("invalid int value for b: %w", err) - } - return cmpInt(ai, bi), nil - - case t.IsUnsignedInt(): - ai, err := toUint(a, t.BitSize()) - if err != nil { - return 0, fmt.Errorf("invalid uint value for a: %w", err) - } - bi, err := toUint(b, t.BitSize()) - if err != nil { - return 0, fmt.Errorf("invalid uint value for b: %w", err) - } - return cmpUint(ai, bi), nil - - case t.IsFloat(): - af, err := toFloat(a, t.BitSize()) - if err != nil { - return 0, fmt.Errorf("invalid float value for a: %w", err) - } - bf, err := toFloat(b, t.BitSize()) - if err != nil { - return 0, fmt.Errorf("invalid float value for b: %w", err) - } - return cmpFloat64(af, bf), nil - - case t == StateType_Boolean: - ab, err := toBool(a) - if err != nil { - return 0, fmt.Errorf("invalid bool value for a: %w", err) - } - bb, err := toBool(b) - if err != nil { - return 0, fmt.Errorf("invalid bool value for b: %w", err) - } - return cmpBool(ab, bb), nil - - case t == StateType_String || t == StateType_Char: - as, err := toString(a) - if err != nil { - return 0, fmt.Errorf("invalid string value for a") - } - bs, err := toString(b) - if err != nil { - return 0, fmt.Errorf("invalid string value for b") - } - return strings.Compare(as, bs), nil - - case t.IsTime(): - at, err := toTime(a) - if err != nil { - return 0, fmt.Errorf("invalid time value for a") - } - bt, err := toTime(b) - if err != nil { - return 0, fmt.Errorf("invalid time value for b") - } - return cmpTime(at, bt), nil - - default: - return 0, fmt.Errorf("comparison not supported for type %v", t) - } -} - -func (t StateVarType) Equal(a, b interface{}) (bool, error) { - switch { - case t.IsInteger(): - ai, err1 := toInt(a, 64) - bi, err2 := toInt(b, 64) - if err1 != nil || err2 != nil { - return false, fmt.Errorf("invalid integer value for type %s", t.String()) - } - return ai == bi, nil - - case t.IsFloat(): - af, err := toFloat(a, 64) - if err != nil { - return false, fmt.Errorf("invalid float value for type %s: %v", t.String(), err) - } - bf, err := toFloat(b, 64) - if err != nil { - return false, fmt.Errorf("invalid float value for type %s: %v", t.String(), err) - } - return af == bf, nil - - case t.IsString(): - as, ok1 := a.(string) - bs, ok2 := b.(string) - if !ok1 || !ok2 { - return false, fmt.Errorf("invalid string value for type %s", t.String()) - } - return as == bs, nil - - case t.IsBool(): - ab, err1 := toBool(a) - bb, err2 := toBool(b) - if err1 != nil || err2 != nil { - return false, fmt.Errorf("invalid boolean value for type %s", t.String()) - } - return ab == bb, nil - - case t.IsTime(): - at, err1 := toTime(a) - bt, err2 := toTime(b) - if err1 != nil || err2 != nil { - return false, fmt.Errorf("invalid time.Time value for type %s", t.String()) - } - return at.Equal(bt), nil - - case t.IsUUID(): - au, err1 := toUUID(a) - bu, err2 := toUUID(b) - if err1 != nil || err2 != nil { - return false, fmt.Errorf("invalid uuid.UUID value for type %s", t.String()) - } - return au == bu, nil - - case t.IsURI(): - au, err1 := toURI(a) - bu, err2 := toURI(b) - if err1 != nil || err2 != nil { - return false, fmt.Errorf("invalid *url.URL value for type %s", t.String()) - } - return au.String() == bu.String(), nil - - case t.IsBinary(): - ab, err1 := toBinary(a) - bb, err2 := toBinary(b) - if err1 != nil || err2 != nil { - return false, fmt.Errorf("invalid []byte value for type %s", t.String()) - } - return bytes.Equal(ab, bb), nil - - default: - return false, fmt.Errorf("equality not supported for type %s", t.String()) - } -} - -// InRange checks if a value falls within an inclusive range [min, max]. -// Uses the type's comparison logic. Returns true if val is between min and max (inclusive). -// -// Example: -// -// range := ValueRange{min: uint16(10), max: uint16(100)} -// StateType_UI2.InRange(uint16(50), range) // true -func (t StateVarType) InRange(val interface{}, interval *ValueRange) (bool, error) { - if interval == nil { - return true, nil - } - cmp1, err1 := t.Cmp(val, interval.min) - cmp2, err2 := t.Cmp(val, interval.max) - if err1 != nil || err2 != nil { - err := err1 - if err == nil { - err = err2 - } - return false, err - } - return cmp1 >= 0 && cmp2 <= 0, nil -} ------------------ -------- /pmoupnp/devices/services/statevariables/statevartype_typechecking.go ------ -package statevariables - -// IsNumeric checks whether a given StateVarType represents a numeric type or -// not. Numeric types are defined as those that can be used to store number-like -// values. The following types are considered numeric: UI1, UI2, UI4, I1, I2, -// I4, Int, R4, R8, Number and Fixed14_4. -// -// t: StateVarType to check if it's a numeric type or not. -// -// Returns true if the given StateVarType represents a numeric type; false -// otherwise. -func (t StateVarType) IsNumeric() bool { - switch t { - case StateType_UI1, StateType_UI2, StateType_UI4, - StateType_I1, StateType_I2, StateType_I4, - StateType_Int, - StateType_R4, StateType_R8, - StateType_Number, - StateType_Fixed14_4: - return true - default: - return false - } -} - -// IsInteger checks if the state variable type is integer or not. -// -// It returns a boolean value indicating whether the provided StateVarType (t) -// is an integer type or not. The function takes one parameter, t of type -// StateVarType, which represents the state variable type to be checked. -// -// Parameters: - t (StateVarType): The StateVarType to check for comparability. -// -// Returns: bool: If the state variable type is any of the defined integer types -// (StateType_UI1, StateType_UI2, StateType_UI4, StateType_I1, StateType_I2, -// StateType_I4, StateType_Int), it returns true. Otherwise, it returns false. -func (t StateVarType) IsInteger() bool { - switch t { - case StateType_UI1, StateType_UI2, StateType_UI4, - StateType_I1, StateType_I2, StateType_I4, - StateType_Int: - return true - default: - return false - } -} - -// IsSignedInt checks if the state variable type is a signed integer type. -// The function returns true for StateType_I1, StateType_I2, StateType_I4, and -// StateType_Int, otherwise it will return false. This method is part of the -// StateVarType enumeration in statevaluetype package. It takes no parameters -// but operates on the receiver 't' of type StateVarType. -// -// The returned value is a boolean. -func (t StateVarType) IsSignedInt() bool { - switch t { - case StateType_I1, StateType_I2, StateType_I4, StateType_Int: - return true - default: - return false - } -} - -// IsUnsignedInt checks if the state variable type is an unsigned integer. It -// returns a boolean indicating whether or not the current StateVarType -// represents an unsigned integer type, namely: StateType_UI1, StateType_UI2, -// and StateType_UI4. -func (t StateVarType) IsUnsignedInt() bool { - switch t { - case StateType_UI1, StateType_UI2, StateType_UI4: - return true - default: - return false - } -} - -// IsFloat returns a boolean indicating whether the given state variable type -// represents a float number. If the state variable type is one of R4, R8, Number or -// Fixed14_4 it returns true; otherwise, it returns false. -func (t StateVarType) IsFloat() bool { - switch t { - case StateType_R4, StateType_R8, StateType_Number, StateType_Fixed14_4: - return true - default: - return false - } -} - -// IsBool checks if a StateVarType is of type Boolean. It returns true if the -// StateVarType equals to StateType_Boolean, false otherwise. -func (t StateVarType) IsBool() bool { - return t == StateType_Boolean -} - -// IsString reports whether or not the state variable type represents a string -// value. -// -// This method returns true if the StateVarType is either StateType_String or -// StateType_Char, otherwise it returns false. -func (t StateVarType) IsString() bool { - switch t { - case StateType_String, StateType_Char: - return true - default: - return false - } -} - -// IsTime checks whether a given StateVarType is of time type or not. It accepts -// a StateVarType parameter 't' and returns a boolean value based on the check. -// -// The possible values for 't' are: StateType_Date, StateType_DateTime, -// StateType_DateTimeTZ, StateType_Time, StateType_TimeTZ. If 't' is any of -// these types, the function returns true; otherwise, it returns false. -func (t StateVarType) IsTime() bool { - switch t { - case StateType_Date, StateType_DateTime, StateType_DateTimeTZ, - StateType_Time, StateType_TimeTZ: - return true - default: - return false - } -} - -// IsUUID reports whether the receiver represents a UUID (Universally Unique -// Identifier). The StateVarType should be of type StateType_UUID to return -// true. Otherwise, it returns false. -func (t StateVarType) IsUUID() bool { - return t == StateType_UUID -} - -// IsURI checks if the given state variable type is a URI. -// -// This function returns true if and only if the receiver (StateVarType t) -// equals StateType_URI, which represents URIs in UPnP protocol. Otherwise, it -// returns false. -func (t StateVarType) IsURI() bool { - return t == StateType_URI -} - -// IsBinary checks if the given StateVarType is binary type or not. It returns -// true for types StateType_BinBase64 and StateType_BinHex, otherwise it returns -// false. -func (t StateVarType) IsBinary() bool { - switch t { - case StateType_BinBase64, StateType_BinHex: - return true - default: - return false - } -} - -// IsComparable function checks if a StateVarType is comparable or not. -// -// It returns false for binary types (StateType_BinBase64 and StateType_BinHex) -// as they are non-comparable. For all other types, it returns true indicating -// that these types can be compared. -// -// Parameters: - t (StateVarType): The StateVarType to check for comparability. -// -// Returns: bool: A boolean value indicating whether the given StateVarType is -// comparable or not. True means it's comparable, False means it isn't. -func (t StateVarType) IsComparable() bool { - // Tous les types sauf les binaires sont comparables - switch t { - case StateType_BinBase64, StateType_BinHex: - return false - default: - return true - } -} ------------------ -------- /pmoupnp/devices/services/statevariables/statevartype.go ------ -// package stateVariables provides comprehensive handling of UPnP state variable types. -// It includes type identification, value casting, comparison, and range validation -// for all standard UPnP state variable types. -package statevariables - -import ( - "strings" - "time" -) - -// StateVarType represents UPnP state variable types with corresponding Go type mappings. -type StateVarType int - -// Constants defining all supported UPnP state variable types -const ( - StateType_Unknown StateVarType = iota - StateType_UI1 // Unsigned 8-bit integer (Go: uint8) - StateType_UI2 // Unsigned 16-bit integer (Go: uint16) - StateType_UI4 // Unsigned 32-bit integer (Go: uint32) - StateType_I1 // Signed 8-bit integer (Go: int8) - StateType_I2 // Signed 16-bit integer (Go: int16) - StateType_I4 // Signed 32-bit integer (Go: int32) - StateType_Int // Synonymous with i4 (Go: int32) - StateType_R4 // 32-bit floating point (Go: float32) - StateType_R8 // 64-bit floating point (Go: float64) - StateType_Number // Synonymous with r8 (Go: float64) - StateType_Fixed14_4 // Fixed-point decimal (Go: float64) - StateType_Char // Single Unicode character (Go: rune) - StateType_String // Character string (Go: string) - StateType_Boolean // Boolean value (Go: bool) - StateType_BinBase64 // Base64-encoded binary (Go: []byte) - StateType_BinHex // Hex-encoded binary (Go: []byte) - StateType_Date // Date (YYYY-MM-DD) (Go: time.Time) - StateType_DateTime // DateTime without timezone (Go: time.Time) - StateType_DateTimeTZ // DateTime with timezone (Go: time.Time) - StateType_Time // Time without timezone (Go: time.Time) - StateType_TimeTZ // Time with timezone (Go: time.Time) - StateType_UUID // Universally unique identifier (Go: uuid.UUID) - StateType_URI // Uniform Resource Identifier (Go: *url.URL) -) - -// typeNames maps UPnP XML type names to StateVarType constants -var typeNames = map[string]StateVarType{ - "ui1": StateType_UI1, - "ui2": StateType_UI2, - "ui4": StateType_UI4, - "i1": StateType_I1, - "i2": StateType_I2, - "i4": StateType_I4, - "int": StateType_Int, - "r4": StateType_R4, - "r8": StateType_R8, - "number": StateType_Number, - "fixed.14.4": StateType_Fixed14_4, - "char": StateType_Char, - "string": StateType_String, - "boolean": StateType_Boolean, - "bin.base64": StateType_BinBase64, - "bin.hex": StateType_BinHex, - "date": StateType_Date, - "dateTime": StateType_DateTime, - "dateTime.tz": StateType_DateTimeTZ, - "time": StateType_Time, - "time.tz": StateType_TimeTZ, - "uuid": StateType_UUID, - "uri": StateType_URI, -} - -// typeStrings provides string representations for StateVarType constants -var typeStrings = [...]string{ - "unknown", - "ui1", - "ui2", - "ui4", - "i1", - "i2", - "i4", - "int", - "r4", - "r8", - "number", - "fixed.14.4", - "char", - "string", - "boolean", - "bin.base64", - "bin.hex", - "date", - "dateTime", - "dateTime.tz", - "time", - "time.tz", - "uuid", - "uri", -} - -// StateVarTypeFactory takes a string and attempts to build from it a valid -// StateVarType. The input string is cleaned before processing - -// leading/trailing spaces are trimmed, the case is lowered for comparison with -// known types, and if no match is found 'StateType_Unknown' is returned. -func StateVarTypeFactory(s string) StateVarType { - s = strings.ToLower(strings.TrimSpace(s)) - if val, ok := typeNames[s]; ok { - return val - } - return StateType_Unknown -} - -// String returns a string representation of the StateVarType. It defaults to -// "unknown" if the type is not recognized. -func (t StateVarType) String() string { - if int(t) >= 0 && int(t) < len(typeStrings) { - return typeStrings[t] - } - return "unknown" -} - -// BitSize returns the bit size of the StateVarType value, or -1 if not numeric. -// The possible return values are 8 for StateTypes I1, UI1, and 64 for others. -func (t StateVarType) BitSize() int { - // If t isn't numeric, return -1 - if !t.IsNumeric() { - return -1 - } - - // Check the value of t and return the appropriate bit size - switch t { - case StateType_I1, StateType_UI1: - return 8 - case StateType_I2, StateType_UI2: - return 16 - case StateType_I4, StateType_UI4, StateType_Int, StateType_R4: - return 32 - case StateType_R8, StateType_Number, StateType_Fixed14_4: - return 64 - default: - return 64 - } -} - -// NewStateValue creates and returns a new StateValue struct instance with the given name -// and the receiver's state variable type. The created StateValue is initialized with an -// empty map for event conditions. If name is an empty string, it will cause panic in later -// usage. Name is typically used to identify or represent a specific value or condition -// associated with the variable type 't'. -func (t StateVarType) NewStateValue(name string) *StateVariable { - return &StateVariable{ - name: name, - valueType: t, - eventConditions: make(map[string]StateConditionFunc), - } -} - -func (t StateVarType) DefaultValue() interface{} { - switch t { - case StateType_Unknown: - - case StateType_UI1, StateType_UI2, StateType_UI4: - return uint64(0) - - case StateType_I1, StateType_I2, StateType_I4, StateType_Int: - return int64(0) - - case StateType_R4, StateType_R8, StateType_Number, StateType_Fixed14_4: - return float64(0) - - case StateType_Char, StateType_String: - return "" - case StateType_Boolean: - return false - - case StateType_BinBase64: - return "" - case StateType_BinHex: - return "" - case StateType_Date: - return time.Unix(int64(1718985600), 0).UTC() - case StateType_DateTime: - return time.Unix(int64(1718985600), 0).UTC() - case StateType_DateTimeTZ: - return time.Unix(int64(1718985600), 0).UTC() - case StateType_Time: - return time.Unix(int64(1718985600), 0).UTC() - case StateType_TimeTZ: - return time.Unix(int64(1718985600), 0).UTC() - case StateType_UUID: - return "" - case StateType_URI: - return "" - - } - - return nil -} ------------------