diff options
author | Damien Zammit <damien@zamaudio.com> | 2015-02-16 21:06:35 +1100 |
---|---|---|
committer | Damien Zammit <damien@zamaudio.com> | 2015-02-16 21:06:35 +1100 |
commit | a0ca3ce20d3ca7d3ffcc214c784c9aedd7ecabc6 (patch) | |
tree | d222cfcc96a1ce02e646c0b6138d746c2a2774c7 | |
parent | 0ed0edb04633402615b101a01bbe163dbdeb6ba0 (diff) |
Use librubberband to pitch shift samples for ZamSFZ
Signed-off-by: Damien Zammit <damien@zamaudio.com>
-rw-r--r-- | Makefile.mk | 2 | ||||
-rw-r--r-- | plugins/ZamSFZ/Sfz.cpp | 45 | ||||
-rw-r--r-- | plugins/ZamSFZ/Sfz.hpp | 4 | ||||
-rw-r--r-- | plugins/ZamSFZ/ZamSFZPlugin.cpp | 1 | ||||
-rw-r--r-- | plugins/ZamSFZ/ZamSFZUI.cpp | 4 |
5 files changed, 47 insertions, 9 deletions
diff --git a/Makefile.mk b/Makefile.mk index 9aa5c72..64c15b7 100644 --- a/Makefile.mk +++ b/Makefile.mk @@ -26,7 +26,7 @@ BASE_OPTS = -O2 -ffast-math -fdata-sections -ffunction-sections ifneq ($(NOOPT),true) BASE_OPTS += -mtune=generic -msse -msse2 -mfpmath=sse endif -LINK_OPTS = -fdata-sections -ffunction-sections -Wl,-O1 -Wl,--as-needed -Wl,--gc-sections -Wl,--strip-all $(shell pkg-config --libs sndfile) +LINK_OPTS = -fdata-sections -ffunction-sections -Wl,-O1 -Wl,--as-needed -Wl,--gc-sections -Wl,--strip-all $(shell pkg-config --libs sndfile rubberband) ifeq ($(MACOS),true) # MacOS linker flags diff --git a/plugins/ZamSFZ/Sfz.cpp b/plugins/ZamSFZ/Sfz.cpp index 91ff7e2..eed3099 100644 --- a/plugins/ZamSFZ/Sfz.cpp +++ b/plugins/ZamSFZ/Sfz.cpp @@ -64,13 +64,14 @@ void Sfz::loadsamples(std::string path, std::string filename) } else { for (i = 0; i < maxregions; i++) { for (note = 0; note < 128; note++) { - key = 0; if (sfzinstrument->regions[i]->lokey == sfzinstrument->regions[i]->hikey) { key = sfzinstrument->regions[i]->lokey; } else { key = sfzinstrument->regions[i]->pitch_keycenter; } if (note == key) { + layers[note].keymiddle = key; + layers[note].dsemitones = 0; infile = NULL; if ((infile = sf_open(sfzinstrument->regions[i]->sample.c_str(), SFM_READ, &sfinfo)) == NULL) { printf("Missing samples\n"); @@ -86,16 +87,48 @@ void Sfz::loadsamples(std::string path, std::string filename) sf_close (infile); printf("N-%d V-%d %s\n", note, k, sfzinstrument->regions[i]->sample.c_str()); layers[note].max++; - break; + continue; + } else if (sfzinstrument->regions[i]->lokey <= note && sfzinstrument->regions[i]->hikey >= note) { + layers[note].keymiddle = key; + layers[note].dsemitones = note - key; + //printf("MainKey=%d NoteShiftTo=%d\n", key, note); } } } printf("All samples loaded, Woot!\n"); } delete sfzfile; - for (i = 0; i < 128; i++) { - if (layers[i].max) { - layers[i].max--; +} + +void Sfz::pitchshiftsamples(int srate) +{ + ::RubberBand::RubberBandStretcher* rbl = NULL; + ::RubberBand::RubberBandStretcher* rbr = NULL; + int i,j; + for (i = 0; i < 128; i++) { + //printf("i=%d ds=%d\n", i, layers[i].dsemitones); + if (!(layers[i].dsemitones == 0)) { + int ii = layers[i].keymiddle; + //printf("Pitch shifting... %d\n", layers[i].dsemitones); + for (j = 0; j < layers[ii].max; j++) { + float const * const inl[] = {sample[ii][j][0]}; + float const * const inr[] = {sample[ii][j][1]}; + float * const outl[] = {sample[i][j][0]}; + float * const outr[] = {sample[i][j][1]}; + rbl = new ::RubberBand::RubberBandStretcher(srate, 1, 0, 1.0, pow(2.0, layers[i].dsemitones / 12.)); + rbr = new ::RubberBand::RubberBandStretcher(srate, 1, 0, 1.0, pow(2.0, layers[i].dsemitones / 12.)); + + rbl->setMaxProcessSize(MAX_SAMPLES); + rbr->setMaxProcessSize(MAX_SAMPLES); + rbl->setExpectedInputDuration(MAX_SAMPLES); + rbr->setExpectedInputDuration(MAX_SAMPLES); + rbl->process(inl, MAX_SAMPLES, true); + rbr->process(inr, MAX_SAMPLES, true); + rbl->retrieve(outl, MAX_SAMPLES); + rbr->retrieve(outr, MAX_SAMPLES); + delete rbl; + delete rbr; + } + } } - } } diff --git a/plugins/ZamSFZ/Sfz.hpp b/plugins/ZamSFZ/Sfz.hpp index ce7891e..5698283 100644 --- a/plugins/ZamSFZ/Sfz.hpp +++ b/plugins/ZamSFZ/Sfz.hpp @@ -3,6 +3,7 @@ #include <string.h> #include <ctype.h> #include "libsfz/sfz.h" +#include <rubberband/RubberBandStretcher.h> #include <sndfile.h> #define MAX_LAYERS 8 #define MAX_SAMPLES 64000 @@ -21,6 +22,8 @@ public: typedef struct { int max; + int keymiddle; + int dsemitones; hilo_t l[MAX_LAYERS]; } layer_t; @@ -28,4 +31,5 @@ public: void clearsamples(); void loadsamples(std::string path, std::string filename); void readsamples (SNDFILE *infile, int channels, int note, int layer); + void pitchshiftsamples(int srate); }; diff --git a/plugins/ZamSFZ/ZamSFZPlugin.cpp b/plugins/ZamSFZ/ZamSFZPlugin.cpp index 9c436e5..93ca4a5 100644 --- a/plugins/ZamSFZ/ZamSFZPlugin.cpp +++ b/plugins/ZamSFZ/ZamSFZPlugin.cpp @@ -93,6 +93,7 @@ void ZamSFZPlugin::d_setState(const char* key, const char* value) printf("Path: %s\nFile: %s\n", path.c_str(), filename.c_str()); sfz.clearsamples(); sfz.loadsamples(path, filename); + sfz.pitchshiftsamples((int)d_getSampleRate()); loading = false; } } diff --git a/plugins/ZamSFZ/ZamSFZUI.cpp b/plugins/ZamSFZ/ZamSFZUI.cpp index d5135cf..eccdf02 100644 --- a/plugins/ZamSFZ/ZamSFZUI.cpp +++ b/plugins/ZamSFZ/ZamSFZUI.cpp @@ -130,8 +130,8 @@ void ZamSFZUI::imageButtonClicked(ImageButton*, int) gtk_widget_destroy(dialog); */ - d_setState("filepath", "/home/damien/Music/rhodes-nord/rhodes-nord.sfz"); - //d_setState("filepath", "/home/damien/Music/sfz/sfz LatelyBass/TX_LatelyBass.sfz"); +// d_setState("filepath", "/home/damien/Music/rhodes-nord/rhodes-nord.sfz"); + d_setState("filepath", "/home/damien/Music/sfz/sfz LatelyBass/TX_LatelyBass.sfz"); } void ZamSFZUI::onDisplay() |