xiRetimer

fit recorded audio to a tempo
git clone https://git.ce9e.org/xiRetimer.git

commit
1e7af109b099eae908bfb1620313f93e825fb0b1
parent
15ee73bbef874fa8d95d05295ddcc7bf3db1a137
Author
Tobias Bengfort <tobias.bengfort@gmx.net>
Date
2010-11-06 17:45
start end end fix

Diffstat

M README 1 -
M src/marker.cpp 7 +++++--
M src/marker.h 3 +--
M src/rbprocess.h 40 +++++++++++++++++++++++++++-------------
M src/sample.cpp 12 ++++++------
M xiRetimer 0

6 files changed, 39 insertions, 24 deletions


diff --git a/README b/README

@@ -10,7 +10,6 @@ timestretch - rubberband (v>=1.5)
   10    10 
   11    11 
   12    12 TODO
   13    -1 process (first and last marker should change tempo)
   14    13 smooth interpolation
   15    14 always update gui
   16    15 libmad

diff --git a/src/marker.cpp b/src/marker.cpp

@@ -58,9 +58,9 @@ void Marker::setNew(int pi, float pnew) {
   58    58 int Marker::getInterpolationMode() {return interpolationMode;}
   59    59 void Marker::setInterpolationMode(int m) {interpolationMode=m;}
   60    60 
   61    -1 float Marker::getRatio() {
   -1    61 float Marker::getLengthf() {
   62    62   if (getLength()>0)
   63    -1     return (getNew(getLength()-1)-getNew(0))/(getOld(getLength()-1)-getOld(0));
   -1    63     return getNew(getLength()-1)-getNew(0);
   64    64   else
   65    65     return NULL;
   66    66 }
@@ -72,6 +72,7 @@ float Marker::getRatio(float o) {
   72    72     // linear
   73    73     case 0: {
   74    74       int i=getAreaOld(o);
   -1    75       if (i<0 || i+1>getLength()-1) return 0;
   75    76       float dold=(getOld(i+1)-getOld(i));
   76    77       if (dold<=0) return 0;
   77    78       return (getNew(i+1)-getNew(i))/dold;
@@ -130,6 +131,7 @@ float Marker::old2new(float o) {
  130   131 //    case 0: // linear is default
  131   132     default: {
  132   133       int i=getAreaOld(o);
   -1   134       if (i<0 || i+1>getLength()-1) return 0;
  133   135       // linear interpolation
  134   136       //      n    - n_i        o    - o_i
  135   137       //   -------------- =  --------------
@@ -146,6 +148,7 @@ float Marker::new2old(float n) {
  146   148     // linear
  147   149     case 0: {
  148   150       int i=getAreaNew(n);
   -1   151       if (i<0 || i+1>getLength()-1) return 0;
  149   152       return (n-getNew(i))/(getNew(i+1)-getNew(i))*(getOld(i+1)-getOld(i))+getOld(i);
  150   153     } break;
  151   154     default: {

diff --git a/src/marker.h b/src/marker.h

@@ -15,7 +15,6 @@ For different modes of interpolation you have to edit 3 functions:
   15    15 old2new
   16    16 new2old - inverse of old2new
   17    17 getRatio - derivate of old2new
   18    -1 // TODO define new2old and getRatio from old2new to make sure everything works together
   19    18 */
   20    19 
   21    20 /*
@@ -43,7 +42,7 @@ public:
   43    42   float nnew2new(float n);
   44    43   int getAreaNew(float n);
   45    44   int getAreaOld(float o);
   46    -1   float getRatio(); // factor by wich the whole sample is stretched; used to guess the length of the output array;
   -1    45   float getLengthf(); // factor by wich the length is changed;
   47    46   float getRatio(float o); // factor by wich is stretched on this place;
   48    47   int getInterpolationMode();
   49    48   void setInterpolationMode(int m);

diff --git a/src/rbprocess.h b/src/rbprocess.h

@@ -11,39 +11,52 @@ this is called by sample.process()
   11    11 this uses the rubberband library
   12    12 */
   13    13 
   14    -1 void RBprocess(float* odata, int olength, float* data, int length, Marker* marker, Sample* caller, int n=1) {
   15    -1   // TODO other than linear
   -1    14 int RBprocess(int olength, float* data, int length, Marker* marker, Sample* caller, int n=1) {
   16    15   
   -1    16   int ostart=int(marker->getOld(0)*olength);
   -1    17   if (ostart<0) ostart=0;
   -1    18   int olength2=int(marker->getOld(marker->getLength()-1)*olength)-ostart;
   -1    19   if (olength2>olength-ostart) olength2=olength-ostart;
   -1    20   if (olength2<10) return 1;
   -1    21 
   17    22   float **ibuf = new float *[1];
   18    -1   ibuf[0]=odata;
   -1    23   ibuf[0]=new float[olength2];
   -1    24   for (int i=0; i<olength2; ++i) {
   -1    25     ibuf[0][i]=caller->getOld((ostart+i)/(float)olength);
   -1    26   }
   -1    27 
   19    28   float **obuf = new float *[1];
   20    29   obuf[0]=data;
   21    30 
   22    -1   RubberBand::RubberBandStretcher ts(44100, 1, 0, marker->getRatio());
   23    -1   // map
   -1    31   RubberBand::RubberBandStretcher ts(44100, 1, 0, length/(float)olength2);
   -1    32   // map // TODO not precise
   24    33   std::map<unsigned int, unsigned int> fmap;
   25    34   for (int i=0; i<marker->getLength(); ++i) {
   26    -1     fmap[int(marker->getOld(i)*olength)]=int(marker->getNew(i)*length);
   -1    35     fmap[int(marker->getOld(i)*olength2)]=int(marker->getNew(i)*length);
   27    36     // additional 
   28    37     for (int j=1; j<n; ++j) {
   29    38       float old=(marker->getOld(i+1)-marker->getOld(i))*j/(float)n;
   30    -1       fmap[int(old*olength)]=int(marker->new2nnew(marker->old2new(old))*length);
   -1    39       fmap[int(old*olength2)]=int(marker->new2nnew(marker->old2new(old))*length);
   31    40     }
   32    41   }
   33    42   ts.setKeyFrameMap(fmap);
   34    43 
   35    -1   ts.study(ibuf, olength, true);
   36    -1   ts.setMaxProcessSize(olength);
   -1    44   caller->setFinished(0.03);
   -1    45   ts.study(ibuf, olength2, true);
   -1    46   ts.setMaxProcessSize(olength2);
   37    47   int a1=-1;
   38    48   int a2=0;
   39    -1   caller->setFinished(0.05);
   -1    49   caller->setFinished(0.06);
   40    50   while (a1!=a2) {
   41    -1     ts.process(ibuf, ts.getSamplesRequired(), false);
   -1    51     int sam=ts.getSamplesRequired();
   -1    52     if (sam>olength2/10) sam=olength2/10;
   -1    53     ts.process(ibuf, sam, false);
   42    54     a1=a2;
   43    55     a2=ts.available();
   44    -1     caller->setFinished(a2/(float)length*0.8+0.05); // TODO doesnt work
   -1    56     caller->setFinished(a2/(float)length*0.8+0.05); // TODO doesnt really work
   45    57   }
   46    -1   ts.process(ibuf, olength, true);
   -1    58   caller->setFinished(0.8);
   -1    59   ts.process(ibuf, olength2, true);
   47    60   caller->setFinished(0.95);
   48    61 
   49    62   int avail=ts.available();
@@ -63,6 +76,7 @@ void RBprocess(float* odata, int olength, float* data, int length, Marker* marke
   63    76   delete[] ibuf;
   64    77   delete[] obuf;
   65    78 
   -1    79   return 0;
   66    80 }
   67    81 
   68    82 #endif

diff --git a/src/sample.cpp b/src/sample.cpp

@@ -22,19 +22,19 @@ int Sample::getLength() {
   22    22 }
   23    23 
   24    24 int Sample::getGuessedLength() {
   25    -1   return int(olength*marker->getRatio());
   -1    25   return int(olength*marker->getLengthf());
   26    26 }
   27    27 
   28    28 float Sample::get(float nn) {
   29    -1   if (_processing) return NULL;
   -1    29   if (_processing) return 0;
   30    30   int i=int(length*nn);
   31    -1   if (i<0 || i>=length) return NULL;
   -1    31   if (i<0 || i>=length) return 0;
   32    32   return data[i];
   33    33 }
   34    34 
   35    35 float Sample::getOld(float o) {
   36    36   int i=int((olength-1)*o);
   37    -1   if (i<0 || i>=olength) return NULL;
   -1    37   if (i<0 || i>=olength) return 0;
   38    38   return odata[i];
   39    39 }
   40    40 
@@ -131,12 +131,12 @@ This function does the nmain thing: it stretches the original data as defined by
  131   131 Therefore it reads data from odata and writes to data.
  132   132 */
  133   133   // setup data
  134    -1   length=int(marker->getRatio()*olength);
   -1   134   length=getGuessedLength();
  135   135   delete[] data;
  136   136   data=new float[length];
  137   137   switch (getStretchMode()) {
  138   138     // rubberband
  139    -1     case 1: RBprocess(odata, olength, data, length, marker, this); break;
   -1   139     case 1: RBprocess(olength, data, length, marker, this); break;
  140   140     default: {
  141   141       for (int i=0; i<length; ++i) {
  142   142         data[i]=getOld(marker->new2old(marker->nnew2new(i/(float)length)));

diff --git a/xiRetimer b/xiRetimer

Binary files differ.