From: Paul Brossier Date: Wed, 21 Sep 2016 15:36:50 +0000 (+0200) Subject: src/effects/pitchshift.h: split implementations in two files, move option parsing... X-Git-Url: https://git.aubio.org/?a=commitdiff_plain;h=25a19c2d1f811b89f4e39138a338a16b4255c1eb;p=aubio.git src/effects/pitchshift.h: split implementations in two files, move option parsing to rubberband_utils.c --- diff --git a/src/effects/pitchshift.c b/src/effects/pitchshift.c deleted file mode 100644 index 2b2461fe..00000000 --- a/src/effects/pitchshift.c +++ /dev/null @@ -1,236 +0,0 @@ -/* - Copyright (C) 2016 Paul Brossier - - This file is part of aubio. - - aubio is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - aubio 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with aubio. If not, see . - -*/ - -#include "config.h" -#include "aubio_priv.h" -#include "fvec.h" -#include "effects/pitchshift.h" - -#ifdef HAVE_RUBBERBAND - -#include "rubberband/rubberband-c.h" - -// check rubberband is 1.8.1, warn if 1.3 -#if !((RUBBERBAND_API_MAJOR_VERSION >= 2) && \ - (RUBBERBAND_API_MINOR_VERSION >= 5)) -#warning RubberBandOptionDetectorSoft not available, \ - please upgrade rubberband to version 1.8.1 or higher -#define RubberBandOptionDetectorSoft 0x00000000 -#endif - -/** generic pitch shifting structure */ -struct _aubio_pitchshift_t -{ - uint_t samplerate; /**< samplerate */ - uint_t hopsize; /**< hop size */ - smpl_t pitchscale; /**< pitch scale */ - - RubberBandState rb; - RubberBandOptions rboptions; -}; - -aubio_pitchshift_t * -new_aubio_pitchshift (const char_t * mode, - smpl_t transpose, uint_t hopsize, uint_t samplerate) -{ - aubio_pitchshift_t *p = AUBIO_NEW (aubio_pitchshift_t); - p->samplerate = samplerate; - p->hopsize = hopsize; - p->pitchscale = 1.; - if (transpose >= -24. && transpose <= 24.) { - p->pitchscale = POW(2., transpose / 12.); - } else { - AUBIO_ERR("pitchshift: transpose should be in the range [-24, 24], got %f\n", transpose); - goto beach; - } - - p->rboptions = RubberBandOptionProcessRealTime; - - if ( strcmp(mode,"crispness:0") == 0 ) { - p->rboptions |= RubberBandOptionTransientsSmooth; - p->rboptions |= RubberBandOptionWindowLong; - p->rboptions |= RubberBandOptionPhaseIndependent; - } else if ( strcmp(mode, "crispness:1") == 0 ) { - p->rboptions |= RubberBandOptionDetectorSoft; - p->rboptions |= RubberBandOptionTransientsSmooth; - p->rboptions |= RubberBandOptionWindowLong; - p->rboptions |= RubberBandOptionPhaseIndependent; - } else if ( strcmp(mode, "crispness:2") == 0 ) { - p->rboptions |= RubberBandOptionTransientsSmooth; - p->rboptions |= RubberBandOptionPhaseIndependent; - } else if ( strcmp(mode, "crispness:3") == 0 ) { - p->rboptions |= RubberBandOptionTransientsSmooth; - } else if ( strcmp(mode, "crispness:4") == 0 ) { - // same as "default" - } else if ( strcmp(mode, "crispness:5") == 0 ) { - p->rboptions |= RubberBandOptionTransientsCrisp; - } else if ( strcmp(mode, "crispness:6") == 0 ) { - p->rboptions |= RubberBandOptionTransientsCrisp; - p->rboptions |= RubberBandOptionWindowShort; - p->rboptions |= RubberBandOptionPhaseIndependent; - } else if ( strcmp(mode, "default") == 0 ) { - // nothing to do - } else { - AUBIO_ERR("pitchshift: unknown pitch shifting method %s\n", mode); - goto beach; - } - //AUBIO_MSG("pitchshift: using pitch shifting method %s\n", mode); - - //p->rboptions |= RubberBandOptionTransientsCrisp; - //p->rboptions |= RubberBandOptionWindowStandard; - //p->rboptions |= RubberBandOptionSmoothingOff; - //p->rboptions |= RubberBandOptionFormantShifted; - //p->rboptions |= RubberBandOptionPitchHighConsistency; - p->rb = rubberband_new(samplerate, 1, p->rboptions, 1., p->pitchscale); - rubberband_set_max_process_size(p->rb, p->hopsize); - //rubberband_set_debug_level(p->rb, 10); - -#if 1 - // warm up rubber band - unsigned int latency = MAX(p->hopsize, rubberband_get_latency(p->rb)); - int available = rubberband_available(p->rb); - fvec_t *zeros = new_fvec(p->hopsize); - while (available <= (int)latency) { - rubberband_process(p->rb, (const float* const*)&(zeros->data), p->hopsize, 0); - available = rubberband_available(p->rb); - } - del_fvec(zeros); -#endif - - return p; - -beach: - del_aubio_pitchshift(p); - return NULL; -} - -void -del_aubio_pitchshift (aubio_pitchshift_t * p) -{ - if (p->rb) { - rubberband_delete(p->rb); - } - AUBIO_FREE (p); -} - -uint_t aubio_pitchshift_get_latency (aubio_pitchshift_t * p) { - return rubberband_get_latency(p->rb); -} - -uint_t -aubio_pitchshift_set_pitchscale (aubio_pitchshift_t * p, smpl_t pitchscale) -{ - if (pitchscale >= 0.25 && pitchscale <= 4.) { - p->pitchscale = pitchscale; - rubberband_set_pitch_scale(p->rb, p->pitchscale); - return AUBIO_OK; - } else { - AUBIO_ERR("pitchshift: could not set pitchscale to %.2f\n", pitchscale); - return AUBIO_FAIL; - } -} - -smpl_t -aubio_pitchshift_get_pitchscale (aubio_pitchshift_t * p) -{ - return p->pitchscale; -} - -uint_t -aubio_pitchshift_set_transpose(aubio_pitchshift_t * p, smpl_t transpose) -{ - if (transpose >= -24. && transpose <= 24.) { - smpl_t pitchscale = POW(2., transpose / 12.); - return aubio_pitchshift_set_pitchscale(p, pitchscale); - } else { - AUBIO_ERR("pitchshift: could not set transpose to %.2f\n", transpose); - return AUBIO_FAIL; - } -} - -smpl_t -aubio_pitchshift_get_transpose(aubio_pitchshift_t * p) -{ - return 12. * LOG(p->pitchscale) / LOG(2.0); -} - -void -aubio_pitchshift_do (aubio_pitchshift_t * p, const fvec_t * in, fvec_t * out) -{ - int output = 0; - rubberband_process(p->rb, (const float* const*)&(in->data), p->hopsize, output); - if (rubberband_available(p->rb) >= (int)p->hopsize) { - rubberband_retrieve(p->rb, (float* const*)&(out->data), p->hopsize); - } else { - AUBIO_WRN("pitchshift: catching up with zeros, only %d available, needed: %d, " - "current pitchscale: %f\n", - rubberband_available(p->rb), p->hopsize, p->pitchscale); - fvec_zeros(out); - } -} - -#else - -// TODO fallback pitch shifting implementation - -struct _aubio_pitchshift_t -{ - void *dummy; -}; - -void aubio_pitchshift_do (aubio_pitchshift_t * o UNUSED, const fvec_t * in UNUSED, - fvec_t * out UNUSED) { -} - -void del_aubio_pitchshift (aubio_pitchshift_t * o UNUSED) { -} - -aubio_pitchshift_t *new_aubio_pitchshift (const char_t * method UNUSED, - smpl_t pitchscale UNUSED, uint_t hop_size UNUSED, uint_t samplerate UNUSED) -{ - AUBIO_ERR ("aubio was not compiled with rubberband\n"); - return NULL; -} - -uint_t aubio_pitchshift_set_pitchscale (aubio_pitchshift_t * o UNUSED, smpl_t pitchscale UNUSED) -{ - return AUBIO_FAIL; -} - -smpl_t aubio_pitchshift_get_pitchscale (aubio_pitchshift_t * o UNUSED) -{ - return 1.; -} - -uint_t aubio_pitchshift_set_transpose (aubio_pitchshift_t * o UNUSED, smpl_t transpose UNUSED) { - return AUBIO_FAIL; -} - -smpl_t aubio_pitchshift_get_transpose (aubio_pitchshift_t * o UNUSED) { - return 0.; -} - -uint_t aubio_pitchshift_get_latency (aubio_pitchshift_t * o UNUSED) { - return 0.; -} - -// end of dummy implementation - -#endif /* HAVE_RUBBERBAND */ diff --git a/src/effects/pitchshift_dummy.c b/src/effects/pitchshift_dummy.c new file mode 100644 index 00000000..a43c8cf7 --- /dev/null +++ b/src/effects/pitchshift_dummy.c @@ -0,0 +1,74 @@ +/* + Copyright (C) 2016 Paul Brossier + + This file is part of aubio. + + aubio is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + aubio 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with aubio. If not, see . + +*/ + +#include "config.h" + +#ifndef HAVE_RUBBERBAND + +#include "aubio_priv.h" +#include "fvec.h" +#include "effects/pitchshift.h" + +// TODO fallback pitch shifting implementation + +struct _aubio_pitchshift_t +{ + void *dummy; +}; + +void aubio_pitchshift_do (aubio_pitchshift_t * o UNUSED, const fvec_t * in UNUSED, + fvec_t * out UNUSED) { +} + +void del_aubio_pitchshift (aubio_pitchshift_t * o UNUSED) { +} + +aubio_pitchshift_t *new_aubio_pitchshift (const char_t * method UNUSED, + smpl_t pitchscale UNUSED, uint_t hop_size UNUSED, uint_t samplerate UNUSED) +{ + AUBIO_ERR ("aubio was not compiled with rubberband\n"); + return NULL; +} + +uint_t aubio_pitchshift_set_pitchscale (aubio_pitchshift_t * o UNUSED, smpl_t pitchscale UNUSED) +{ + return AUBIO_FAIL; +} + +smpl_t aubio_pitchshift_get_pitchscale (aubio_pitchshift_t * o UNUSED) +{ + return 1.; +} + +uint_t aubio_pitchshift_set_transpose (aubio_pitchshift_t * o UNUSED, smpl_t transpose UNUSED) { + return AUBIO_FAIL; +} + +smpl_t aubio_pitchshift_get_transpose (aubio_pitchshift_t * o UNUSED) { + return 0.; +} + +uint_t aubio_pitchshift_get_latency (aubio_pitchshift_t * o UNUSED) { + return 0.; +} + +// end of dummy implementation + +#endif /* HAVE_RUBBERBAND */ diff --git a/src/effects/pitchshift_rubberband.c b/src/effects/pitchshift_rubberband.c new file mode 100644 index 00000000..cda63dcd --- /dev/null +++ b/src/effects/pitchshift_rubberband.c @@ -0,0 +1,154 @@ +/* + Copyright (C) 2016 Paul Brossier + + This file is part of aubio. + + aubio is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + aubio 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with aubio. If not, see . + +*/ + +#include "config.h" + +#ifdef HAVE_RUBBERBAND + +#include "aubio_priv.h" +#include "fvec.h" +#include "effects/pitchshift.h" + +#include "rubberband/rubberband-c.h" + +/** generic pitch shifting structure */ +struct _aubio_pitchshift_t +{ + uint_t samplerate; /**< samplerate */ + uint_t hopsize; /**< hop size */ + smpl_t pitchscale; /**< pitch scale */ + + RubberBandState rb; + RubberBandOptions rboptions; +}; + +extern RubberBandOptions aubio_get_rubberband_opts(const char_t *mode); + +aubio_pitchshift_t * +new_aubio_pitchshift (const char_t * mode, + smpl_t transpose, uint_t hopsize, uint_t samplerate) +{ + aubio_pitchshift_t *p = AUBIO_NEW (aubio_pitchshift_t); + p->samplerate = samplerate; + p->hopsize = hopsize; + p->pitchscale = 1.; + if (transpose >= -24. && transpose <= 24.) { + p->pitchscale = POW(2., transpose / 12.); + } else { + AUBIO_ERR("pitchshift: transpose should be in the range [-24, 24], got %f\n", transpose); + goto beach; + } + + p->rboptions = aubio_get_rubberband_opts(mode); + if (p->rboptions < 0) { + AUBIO_ERR("timestretch: unknown pitch shifting method %s\n", mode); + goto beach; + } + //AUBIO_MSG("pitchshift: using pitch shifting method %s\n", mode); + + p->rb = rubberband_new(samplerate, 1, p->rboptions, 1., p->pitchscale); + rubberband_set_max_process_size(p->rb, p->hopsize); + //rubberband_set_debug_level(p->rb, 10); + +#if 1 + // warm up rubber band + unsigned int latency = MAX(p->hopsize, rubberband_get_latency(p->rb)); + int available = rubberband_available(p->rb); + fvec_t *zeros = new_fvec(p->hopsize); + while (available <= (int)latency) { + rubberband_process(p->rb, (const float* const*)&(zeros->data), p->hopsize, 0); + available = rubberband_available(p->rb); + } + del_fvec(zeros); +#endif + + return p; + +beach: + del_aubio_pitchshift(p); + return NULL; +} + +void +del_aubio_pitchshift (aubio_pitchshift_t * p) +{ + if (p->rb) { + rubberband_delete(p->rb); + } + AUBIO_FREE (p); +} + +uint_t aubio_pitchshift_get_latency (aubio_pitchshift_t * p) { + return rubberband_get_latency(p->rb); +} + +uint_t +aubio_pitchshift_set_pitchscale (aubio_pitchshift_t * p, smpl_t pitchscale) +{ + if (pitchscale >= 0.25 && pitchscale <= 4.) { + p->pitchscale = pitchscale; + rubberband_set_pitch_scale(p->rb, p->pitchscale); + return AUBIO_OK; + } else { + AUBIO_ERR("pitchshift: could not set pitchscale to %.2f\n", pitchscale); + return AUBIO_FAIL; + } +} + +smpl_t +aubio_pitchshift_get_pitchscale (aubio_pitchshift_t * p) +{ + return p->pitchscale; +} + +uint_t +aubio_pitchshift_set_transpose(aubio_pitchshift_t * p, smpl_t transpose) +{ + if (transpose >= -24. && transpose <= 24.) { + smpl_t pitchscale = POW(2., transpose / 12.); + return aubio_pitchshift_set_pitchscale(p, pitchscale); + } else { + AUBIO_ERR("pitchshift: could not set transpose to %.2f\n", transpose); + return AUBIO_FAIL; + } +} + +smpl_t +aubio_pitchshift_get_transpose(aubio_pitchshift_t * p) +{ + return 12. * LOG(p->pitchscale) / LOG(2.0); +} + +void +aubio_pitchshift_do (aubio_pitchshift_t * p, const fvec_t * in, fvec_t * out) +{ + int output = 0; + rubberband_process(p->rb, (const float* const*)&(in->data), p->hopsize, output); + if (rubberband_available(p->rb) >= (int)p->hopsize) { + rubberband_retrieve(p->rb, (float* const*)&(out->data), p->hopsize); + } else { + AUBIO_WRN("pitchshift: catching up with zeros, only %d available, needed: %d, " + "current pitchscale: %f\n", + rubberband_available(p->rb), p->hopsize, p->pitchscale); + fvec_zeros(out); + } +} + +#endif diff --git a/src/effects/rubberband_utils.c b/src/effects/rubberband_utils.c new file mode 100644 index 00000000..55dbe3cc --- /dev/null +++ b/src/effects/rubberband_utils.c @@ -0,0 +1,58 @@ + + +#include "config.h" +#include "aubio_priv.h" + +#ifdef HAVE_RUBBERBAND + +#include "rubberband/rubberband-c.h" + +// check rubberband is 1.8.1, warn if 1.3 +#if !((RUBBERBAND_API_MAJOR_VERSION >= 2) && \ + (RUBBERBAND_API_MINOR_VERSION >= 5)) +#warning RubberBandOptionDetectorSoft not available, \ + please upgrade rubberband to version 1.8.1 or higher +#define RubberBandOptionDetectorSoft 0x00000000 +#endif + +RubberBandOptions aubio_get_rubberband_opts(const char_t *mode) +{ + RubberBandOptions rboptions = RubberBandOptionProcessRealTime; + + if ( strcmp(mode,"crispness:0") == 0 ) { + rboptions |= RubberBandOptionTransientsSmooth; + rboptions |= RubberBandOptionWindowLong; + rboptions |= RubberBandOptionPhaseIndependent; + } else if ( strcmp(mode, "crispness:1") == 0 ) { + rboptions |= RubberBandOptionDetectorSoft; + rboptions |= RubberBandOptionTransientsSmooth; + rboptions |= RubberBandOptionWindowLong; + rboptions |= RubberBandOptionPhaseIndependent; + } else if ( strcmp(mode, "crispness:2") == 0 ) { + rboptions |= RubberBandOptionTransientsSmooth; + rboptions |= RubberBandOptionPhaseIndependent; + } else if ( strcmp(mode, "crispness:3") == 0 ) { + rboptions |= RubberBandOptionTransientsSmooth; + } else if ( strcmp(mode, "crispness:4") == 0 ) { + // same as "default" + } else if ( strcmp(mode, "crispness:5") == 0 ) { + rboptions |= RubberBandOptionTransientsCrisp; + } else if ( strcmp(mode, "crispness:6") == 0 ) { + rboptions |= RubberBandOptionTransientsCrisp; + rboptions |= RubberBandOptionWindowShort; + rboptions |= RubberBandOptionPhaseIndependent; + } else if ( strcmp(mode, "default") == 0 ) { + // nothing to do + } else { + // failed parsing option string + return -1; + } + // other options to include + //p->rboptions |= RubberBandOptionWindowStandard; + //p->rboptions |= RubberBandOptionSmoothingOff; + //p->rboptions |= RubberBandOptionFormantShifted; + //p->rboptions |= RubberBandOptionPitchHighConsistency; + return rboptions; +} + +#endif