From 103513b186b3d978a5e82d1e5f171ebdce1062bf Mon Sep 17 00:00:00 2001 From: Geraint Luff Date: Mon, 11 Aug 2025 17:30:09 +0100 Subject: [PATCH] Add asymmetry parameter --- CMakeLists.txt | 2 +- cmd/Makefile | 26 +++++++++++++------------- cmd/main.cpp | 5 +++-- signalsmith-stretch.h | 5 +++-- 4 files changed, 20 insertions(+), 18 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dfb23d5..ffe805b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ include(FetchContent) FetchContent_Declare( signalsmith-linear GIT_REPOSITORY https://github.com/Signalsmith-Audio/linear.git - GIT_TAG 0.2.3 + GIT_TAG 0.2.4 GIT_SHALLOW ON ) FetchContent_MakeAvailable(signalsmith-linear) diff --git a/cmd/Makefile b/cmd/Makefile index 6887a65..abd3678 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -11,19 +11,19 @@ out/stretch: main.cpp ../signalsmith-stretch.h util/*.h util/*.hxx # Uses input files from: https://signalsmith-audio.co.uk/code/stretch/inputs.zip examples: out/stretch mkdir -p out/examples - inputs/run-all.sh out/examples/u2- out/stretch --semitones=2 - inputs/run-all.sh out/examples/d2- out/stretch --semitones=-2 - inputs/run-all.sh out/examples/u4- out/stretch --semitones=4 - inputs/run-all.sh out/examples/d4- out/stretch --semitones=-4 - inputs/run-all.sh out/examples/u8- out/stretch --semitones=8 - inputs/run-all.sh out/examples/d8- out/stretch --semitones=-8 - inputs/run-all.sh out/examples/u16- out/stretch --semitones=16 - inputs/run-all.sh out/examples/d16- out/stretch --semitones=-16 - inputs/run-all.sh out/examples/t_8- out/stretch --time=0.8 - inputs/run-all.sh out/examples/t1_2- out/stretch --time=1.2 - inputs/run-all.sh out/examples/t1_5- out/stretch --time=1.5 - inputs/run-all.sh out/examples/t2- out/stretch --time=2 - inputs/run-all.sh out/examples/t4- out/stretch --time=4 + inputs/run-all.sh out/examples/u2- out/stretch --semitones=2 --asymmetry=0.5 + inputs/run-all.sh out/examples/d2- out/stretch --semitones=-2 --asymmetry=0.5 + inputs/run-all.sh out/examples/u4- out/stretch --semitones=4 --asymmetry=0.5 + inputs/run-all.sh out/examples/d4- out/stretch --semitones=-4 --asymmetry=0.5 + inputs/run-all.sh out/examples/u8- out/stretch --semitones=8 --asymmetry=0.5 + inputs/run-all.sh out/examples/d8- out/stretch --semitones=-8 --asymmetry=0.5 + inputs/run-all.sh out/examples/u16- out/stretch --semitones=16 --asymmetry=0.5 + inputs/run-all.sh out/examples/d16- out/stretch --semitones=-16 --asymmetry=0.5 + inputs/run-all.sh out/examples/t_8- out/stretch --time=0.8 --asymmetry=0.5 + inputs/run-all.sh out/examples/t1_2- out/stretch --time=1.2 --asymmetry=0.5 + inputs/run-all.sh out/examples/t1_5- out/stretch --time=1.5 --asymmetry=0.5 + inputs/run-all.sh out/examples/t2- out/stretch --time=2 --asymmetry=0.5 + inputs/run-all.sh out/examples/t4- out/stretch --time=4 --asymmetry=0.5 TEST_WAV ?= "inputs/voice.wav" diff --git a/cmd/main.cpp b/cmd/main.cpp index 0ff29ea..87c1eb2 100644 --- a/cmd/main.cpp +++ b/cmd/main.cpp @@ -19,12 +19,13 @@ int main(int argc, char* argv[]) { std::string inputWav = args.arg("input.wav", "16-bit WAV file"); std::string outputWav = args.arg("output.wav", "output WAV file"); + double time = args.flag("time", "time-stretch factor", 1); double semitones = args.flag("semitones", "pitch-shift amount", 0); double formants = args.flag("formant", "formant-shift amount (semitones)", 0); bool formantComp = args.hasFlag("formant-comp", "formant compensation"); double formantBase = args.flag("formant-base", "formant base frequency (Hz, 0=auto)", 100); double tonality = args.flag("tonality", "tonality limit (Hz)", 8000); - double time = args.flag("time", "time-stretch factor", 1); + double asymmetry = args.flag("asymmetry", "asymmetrical STFT analysis (0-1)", 0); bool splitComputation = args.hasFlag("split-computation", "distributes the computation more evenly (but higher latency)"); args.errorExit(); // exits on error, or with `--help` @@ -42,7 +43,7 @@ int main(int argc, char* argv[]) { outWav.resize(outputLength); SignalsmithStretch stretch; - stretch.presetDefault(int(inWav.channels), inWav.sampleRate, splitComputation); + stretch.configure(int(inWav.channels), inWav.sampleRate*0.12, inWav.sampleRate*0.03, splitComputation, asymmetry); stretch.setTransposeSemitones(semitones, tonality/inWav.sampleRate); stretch.setFormantSemitones(formants, formantComp); stretch.setFormantBase(formantBase/inWav.sampleRate); diff --git a/signalsmith-stretch.h b/signalsmith-stretch.h index e05406c..effc0fb 100644 --- a/signalsmith-stretch.h +++ b/signalsmith-stretch.h @@ -68,11 +68,12 @@ struct SignalsmithStretch { } // Manual setup - void configure(int nChannels, int blockSamples, int intervalSamples, bool splitComputation=false) { + void configure(int nChannels, int blockSamples, int intervalSamples, bool splitComputation=false, Sample asymmetry=0) { _splitComputation = splitComputation; channels = nChannels; + asymmetry *= 1 - 2.0*intervalSamples/blockSamples; // maximum asymmetry gives latency of two intervals stft.configure(channels, channels, blockSamples, intervalSamples + 1); - stft.setInterval(intervalSamples, stft.kaiser); + stft.setInterval(intervalSamples, stft.kaiser, asymmetry); stft.reset(0.1); stashedInput = stft.input; stashedOutput = stft.output;