Generator.cc

Go to the documentation of this file.
00001 
00002 //
00003 //  $Id: Generator.cc 718 2012-04-15 23:59:35Z weegreenblobbie $
00004 //
00005 //  Copyright (c) 2005-2006 Nick Hilton
00006 //
00007 //  weegreenblobbie_yahoo_com (replace '_' with '@' and '.')
00008 //
00010 
00012 //
00013 //  This program is free software; you can redistribute it and/or modify
00014 //  it under the terms of the GNU General Public License as published by
00015 //  the Free Software Foundation; either version 2 of the License, or
00016 //  (at your option) any later version.
00017 //
00018 //  This program is distributed in the hope that it will be useful,
00019 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00020 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00021 //  GNU Library General Public License for more details.
00022 //
00023 //  You should have received a copy of the GNU General Public License
00024 //  along with this program; if not, write to the Free Software
00025 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00026 //
00028 
00029 #include <Nsound/Buffer.h>
00030 #include <Nsound/Generator.h>
00031 #include <Nsound/RngTausworthe.h>
00032 
00033 #include <cmath>
00034 #include <string.h>
00035 #include <iostream>
00036 
00037 using namespace Nsound;
00038 
00039 using std::cout;
00040 using std::cerr;
00041 using std::endl;
00042 
00043 #define M_2PI (2.0*M_PI)
00044 
00045 #define CERR_HEADER __FILE__ << ":" << __LINE__ << ": "
00046 
00048 // Constructor
00050 Generator::
00051 Generator()
00052     :
00053     last_frequency_(0.0),
00054     position_(0.0),
00055     sample_rate_(0.0),
00056     sample_time_(0.0),
00057     t_(0.0),
00058     waveform_(NULL),
00059     rng_(NULL),
00060     buzz_max_harmonics_(0),
00061     buzz_position_(),
00062     chorus_is_on_(false),
00063     chorus_n_voices_(0),
00064     chorus_position_(),
00065     chorus_factor_(),
00066     sync_is_master_(false),
00067     sync_is_slave_(false),
00068     sync_count_(0),
00069     sync_vector_(),
00070     sync_slaves_()
00071 {
00072 };
00073 
00075 // Constructor
00077 Generator::
00078 Generator(const float64 & sample_rate)
00079     :
00080     last_frequency_(0.0),
00081     position_(0.0),
00082     sample_rate_(0.0),
00083     sample_time_(0.0),
00084     t_(0.0),
00085     waveform_(NULL),
00086     rng_(NULL),
00087     buzz_max_harmonics_(0),
00088     buzz_position_(),
00089     chorus_is_on_(false),
00090     chorus_n_voices_(0),
00091     chorus_position_(),
00092     chorus_factor_(),
00093     sync_is_master_(false),
00094     sync_is_slave_(false),
00095     sync_count_(0),
00096     sync_vector_(),
00097     sync_slaves_()
00098 {
00099     ctor(sample_rate);
00100 }
00101 
00103 // Constructor
00105 Generator::
00106 Generator(const std::string & wave_filename)
00107     :
00108     last_frequency_(0.0),
00109     position_(0.0),
00110     sample_rate_(0.0),
00111     sample_time_(0.0),
00112     t_(0.0),
00113     waveform_(NULL),
00114     rng_(NULL),
00115     buzz_max_harmonics_(0),
00116     buzz_position_(),
00117     chorus_is_on_(false),
00118     chorus_n_voices_(0),
00119     chorus_position_(),
00120     chorus_factor_(),
00121     sync_is_master_(false),
00122     sync_is_slave_(false),
00123     sync_count_(0),
00124     sync_vector_(),
00125     sync_slaves_()
00126 {
00127     Buffer b(wave_filename);
00128     ctor(b.getLength(), b);
00129 }
00130 
00132 // Constructor
00134 Generator::
00135 Generator(const float64 & sample_rate, const Buffer & waveform)
00136     :
00137     last_frequency_(0.0),
00138     position_(0.0),
00139     sample_rate_(0.0),
00140     sample_time_(0.0),
00141     t_(0.0),
00142     waveform_(NULL),
00143     rng_(NULL),
00144     buzz_max_harmonics_(0),
00145     buzz_position_(),
00146     chorus_is_on_(false),
00147     chorus_n_voices_(0),
00148     chorus_position_(),
00149     chorus_factor_(),
00150     sync_is_master_(false),
00151     sync_is_slave_(false),
00152     sync_count_(0),
00153     sync_vector_(),
00154     sync_slaves_()
00155 {
00156     ctor(sample_rate, waveform);
00157 }
00158 
00160 // Copy Constructor
00162 Generator::
00163 Generator(const Generator & gen)
00164     :
00165     last_frequency_(0.0),
00166     position_(0.0),
00167     sample_rate_(0.0),
00168     sample_time_(0.0),
00169     t_(0.0),
00170     waveform_(NULL),
00171     rng_(NULL),
00172     buzz_max_harmonics_(0),
00173     buzz_position_(),
00174     chorus_is_on_(false),
00175     chorus_n_voices_(0),
00176     chorus_position_(),
00177     chorus_factor_(),
00178     sync_is_master_(false),
00179     sync_is_slave_(false),
00180     sync_count_(0),
00181     sync_vector_(),
00182     sync_slaves_()
00183 {
00184     // Call operator=
00185     *this = gen;
00186 }
00187 
00189 // Destructor
00191 Generator::
00192 ~Generator()
00193 {
00194     delete waveform_;
00195     delete rng_;
00196 };
00197 
00199 // ctor
00201 void
00202 Generator::
00203 ctor(const float64 & sample_rate)
00204 {
00205     sample_rate_ = sample_rate;
00206     sample_time_ = 1.0 / sample_rate_;
00207     waveform_ = NULL;
00208     rng_ = new RngTausworthe();
00209 }
00210 
00212 // ctor
00214 void
00215 Generator::
00216 ctor(const float64 & sample_rate, const Buffer & waveform)
00217 {
00218     if(waveform.getLength() != sample_rate)
00219     {
00220         cerr << ERROR_HEADER << "waveform.getLength() != sample_rate ("
00221              << waveform.getLength()
00222              << " != "
00223              << sample_rate
00224              << ")"
00225              << endl;
00226 
00227         ctor(sample_rate);
00228     }
00229     else
00230     {
00231         sample_rate_ = sample_rate;
00232         sample_time_ = 1.0 / sample_rate_;
00233         waveform_ = new Buffer(waveform);
00234         rng_ = new RngTausworthe();
00235     }
00236 }
00237 
00239 void
00240 Generator::
00241 addSlaveSync(Generator & slave)
00242 {
00243     sync_is_master_ = true;
00244     slave.sync_is_slave_ = true;
00245 
00246     // Only add if it is unique.
00247     std::vector<Generator *>::iterator itor = sync_slaves_.begin();
00248     std::vector<Generator *>::iterator end = sync_slaves_.end();
00249 
00250     boolean is_found = false;
00251 
00252     while(itor != end)
00253     {
00254         if(*itor == &slave) is_found = true;
00255 
00256         ++itor;
00257     }
00258 
00259     if(!is_found) sync_slaves_.push_back(&slave);
00260 
00261     reset();
00262 }
00263 
00265 void
00266 Generator::
00267 buzzInit(const uint32 & max_harmonics)
00268 {
00269     buzz_max_harmonics_ = max_harmonics;
00270     reset();
00271 }
00272 
00274 float64
00275 Generator::
00276 buzz(
00277     const float64 & frequency,
00278     const float64 & n_harmonics,
00279     const float64 & phase_offset)
00280 {
00281     // This function is based on the csound buzz opcode.
00282 
00283     float64 n = static_cast<int32>(n_harmonics);
00284 
00285     n = fabs(n);
00286     if(n < 1.0) n = 1.0;
00287 
00288     float64 two_n_plus_1 = 2.0 * n + 1.0;
00289     float64 scale = static_cast<float64>(0.5) / n;
00290 
00291     float64 sign = 1.0;
00292     for(int i = 0; i < n; ++i) sign = -sign;
00293 
00294     float64 phase = fabs(phase_offset / static_cast<float64>(2.0));
00295 
00296     while(phase >= 0.5) phase -= 0.5;
00297 
00298     position_ += (phase - last_frequency_) * sample_rate_;
00299 
00300     last_frequency_ = phase;
00301 
00302     float64 y;
00303 
00304     while(position_ >= sample_rate_) position_ -= sample_rate_;
00305 
00306     float64 denom = (*waveform_)[static_cast<int32>(position_ + 0.5)] * sign;
00307 
00308     if(fabs(denom) > 1e-12)
00309     {
00310         float64 up_phase = position_ * two_n_plus_1;
00311         while(up_phase >= sample_rate_) up_phase -= sample_rate_;
00312 
00313         float64 num = (*waveform_)[static_cast<int32>(up_phase)];
00314 
00315         y = (num / denom - static_cast<float64>(1.0)) * scale;
00316     }
00317     else
00318     {
00319         y = 1.0; // this assumes cosine wave!
00320     }
00321 
00322     position_ += 0.5*frequency;
00323 
00324     return y;
00325 }
00326 
00328 Buffer
00329 Generator::
00330 buzz(
00331     const float64 & duration,
00332     const float64 & frequency,
00333     const float64 & n_harmonics,
00334     const float64 & phase_offset)
00335 {
00336     buzzInit(static_cast<uint32>(n_harmonics));
00337 
00338     int32 n_samples = static_cast<int32>(duration * sample_rate_);
00339 
00340     Buffer y(n_samples);
00341 
00342     for(int i = 0; i < n_samples; ++i)
00343     {
00344         y << buzz(frequency, n_harmonics, phase_offset+0.5);
00345     }
00346 
00347     return y;
00348 }
00349 
00351 Buffer
00352 Generator::
00353 buzz(
00354     const float64 & duration,
00355     const Buffer &  frequencies,
00356     const Buffer &  n_harmonics,
00357     const Buffer &  phase_offset)
00358 {
00359     buzzInit(static_cast<uint32>(n_harmonics.getMax()));
00360 
00361     int32 n_samples = static_cast<int32>(duration * sample_rate_);
00362 
00363     Buffer::circular_iterator f = frequencies.cbegin();
00364     Buffer::circular_iterator n = n_harmonics.cbegin();
00365     Buffer::circular_iterator p = phase_offset.cbegin();
00366 
00367     Buffer y(n_samples);
00368 
00369     for(int32 i = 0; i < n_samples; ++i, ++f, ++n, ++p)
00370     {
00371         y << buzz(*f, *n, *p+0.5);
00372     }
00373 
00374     return y;
00375 }
00376 
00378 void
00379 Generator::
00380 setChorus(const uint32 n_voices, const float64 & amount)
00381 {
00382     if(n_voices == 0)
00383     {
00384         chorus_is_on_ = false;
00385         return;
00386     }
00387 
00388     chorus_is_on_ = true;
00389 
00390     chorus_n_voices_ = n_voices;
00391 
00392     chorus_factor_.clear();
00393     chorus_position_.clear();
00394 
00395     for(uint32 i = 0; i < chorus_n_voices_; ++i)
00396     {
00397         chorus_factor_.push_back(1.0 + rng_->get(-amount, amount));
00398 
00399         chorus_position_.push_back(0.0);
00400     }
00401 
00402     reset();
00403 }
00404 
00406 Buffer
00407 Generator::
00408 drawDecay(const float64 & duration, const float64 & alpha) const
00409 {
00410     if(duration <= 0.0) return Buffer();
00411 
00412     Buffer t = drawLine(duration, 0.0, 1.0);
00413 
00414     t *= -alpha;
00415 
00416     t.exp();
00417 
00418     return t;
00419 }
00420 
00422 Buffer
00423 Generator::
00424 drawGaussian(
00425     const float64 & duration,
00426     const float64 & mu,
00427     const float64 & sigma,
00428     const boolean & normalize) const
00429 {
00430     if(duration <= 0.0) return Buffer();
00431 
00432     float64 variance = sigma * sigma;
00433 
00434     Buffer g = drawLine(duration, 0.0, duration);
00435 
00436     g -= mu;
00437 
00438     g *= g;
00439 
00440     g /= (2.0 * variance);
00441 
00442     g *= -1.0;
00443 
00444     g.exp();
00445 
00446     g /= ::sqrt(M_2PI * variance);
00447 
00448     if(normalize) g.normalize();
00449 
00450     return g;
00451 }
00452 
00454 Buffer
00455 Generator::
00456 drawFatGaussian(
00457     const float64 & duration,
00458     const float64 & pass_band_percent) const
00459 {
00460     if(duration <= 0.0) return Buffer();
00461 
00462     if(pass_band_percent <= 0.0)
00463     {
00464         std::cerr
00465             << CERR_HEADER
00466             << "drawFatGaussian(): Warning: creating all zero Buffer!"
00467             << std::endl;
00468 
00469         return drawLine(duration, 0.0, 0.0);
00470     }
00471 
00472     else if(pass_band_percent >= 1.0)
00473     {
00474         std::cerr
00475             << CERR_HEADER
00476             << "drawFatGaussian(): Warning: creating all 1.0 Buffer!"
00477             << std::endl;
00478 
00479         return drawLine(duration, 1.0, 1.0);
00480     }
00481 
00482     float64 pass_band_time = duration * pass_band_percent;
00483 
00484     float64 gauss_time = duration - pass_band_time;
00485 
00486     float64 h_gauss_time = gauss_time / 2.0;
00487 
00488     // Using a constant sigma ratio so the shape of the fat gaussian doesn't
00489     // change given a duration.
00490 
00491     float64 sigma = 0.275 * h_gauss_time;
00492 
00493     Buffer y;
00494 
00495     y << drawGaussian(h_gauss_time, h_gauss_time, sigma)
00496       << drawLine(pass_band_time, 1.0, 1.0)
00497       << drawGaussian(h_gauss_time, 0.0, sigma);
00498 
00499     return y;
00500 }
00501 
00503 Buffer
00504 Generator::
00505 drawLine(
00506     const float64 & duration,
00507     const float64 & y1,
00508     const float64 & y2) const
00509 {
00510     if(duration <= 0.0) return Buffer();
00511 
00512     Buffer buffer;
00513 
00514     float64 n_samples = duration * sample_rate_;
00515 
00516     float64 slope = (y2 - y1) / n_samples;
00517 
00518     float64 current_sample = y1;
00519 
00520     for(uint32 i = 0; i < static_cast<uint32>(n_samples+0.5); ++i)
00521     {
00522         buffer << current_sample;
00523         current_sample += slope;
00524     }
00525 
00526     return buffer;
00527 }
00528 
00530 Buffer
00531 Generator::
00532 drawParabola(
00533     const float64 & duration,
00534     const float64 & y1,
00535     const float64 & x2,
00536     const float64 & y2,
00537     const float64 & y3) const
00538 {
00539     if(duration <= 0.0) return Buffer();
00540 
00541     // In this discustion, amp = amplitude.
00542     //
00543     // The general equation for a parabola is:
00544     //
00545     // y = A*x^2 + B*x + C
00546     //
00547     // This alogorithm uses Gaussian elimination to solve for A,B,C.
00548     //
00549     // y1 = A * x1^2 + B * x1 + C            (1)
00550     //
00551     // y2 = A * x2^2 + B * x2 + C            (2)
00552     //
00553     // y3 = A * x3^2 + B * x3 + C            (3)
00554     //
00555     // Solve for C using (1), with x1 = 0.0:
00556     //
00557     // C = y1
00558     //
00559     // Solve for A using (2) and substituting C:
00560     //
00561     // A = (y2 - y1 - B * x2) / (x2^2)
00562     //
00563     // Solve for B using (3) and substituting A,C, I used WolframAlpha, awesome!
00564     //
00565     // solve y_3 = (y_2 - y_1 - B*x_2) / (x_2 * x_2) * (x_3 * x_3) + B*(x_3) + y_1 for B
00566     //
00567     //  B = [x2 * x2 * ( y3 - y1 ) + x3 * x3 * (y1 - y2)] / [x2 * x3 * (x2 - x3)]
00568     //
00569     if (x2 >= duration)
00570     {
00571         std::cerr
00572             << CERR_HEADER
00573             << "drawParabola(): x2 > duration"
00574             << std::endl;
00575 
00576         return Buffer();
00577     }
00578 
00579     float64 x3 = duration;
00580 
00581     float64 C = y1;
00582 
00583     float64 B = (  x2*x2*(y3 - y1) + x3*x3*(y1 - y2)  ) / ( x2*x3*(x2 - x3) );
00584 
00585     float64 A = (y2 - y1 - B*x2) / (x2*x2);
00586 
00587     Buffer t = drawLine(duration, 0.0, duration);
00588 
00589     return A*t*t + B*t + C;
00590 }
00591 
00593 Buffer
00594 Generator::
00595 drawSine(
00596     const float64 & duration,
00597     const float64 & frequency)
00598 {
00599     if(duration <= 0.0) return Buffer();
00600 
00601     t_ = 0.0;
00602 
00603     Buffer y;
00604 
00605     uint64 n_samples = static_cast<uint64>(duration * sample_rate_ + 0.5);
00606 
00607     for(uint64 i = 0; i < n_samples; ++i)
00608     {
00609         y << drawSine2(frequency, 0.0);
00610     }
00611 
00612     return y;
00613 }
00614 
00616 Buffer
00617 Generator::
00618 drawSine(
00619     const float64 & duration,
00620     const Buffer & frequency)
00621 {
00622     if(duration <= 0.0) return Buffer();
00623 
00624     t_ = 0.0;
00625 
00626     Buffer y;
00627 
00628     uint64 n_samples = static_cast<uint64>(duration * sample_rate_ + 0.5);
00629 
00630     Buffer::circular_iterator f = frequency.cbegin();
00631 
00632     for(uint64 i = 0; i < n_samples; ++i)
00633     {
00634         y << drawSine2(*f, 0.0);
00635         ++f;
00636     }
00637 
00638     return y;
00639 }
00640 
00642 Buffer
00643 Generator::
00644 drawSine2(
00645     const float64 & duration,
00646     const float64 & frequency,
00647     const float64 & phase)
00648 {
00649     if(duration <= 0.0) return Buffer();
00650 
00651     t_ = 0.0;
00652 
00653     Buffer y;
00654 
00655     uint64 n_samples = static_cast<uint64>(duration * sample_rate_ + 0.5);
00656 
00657     for(uint64 i = 0; i < n_samples; ++i)
00658     {
00659         y << drawSine2(frequency, phase);
00660     }
00661 
00662     return y;
00663 }
00664 
00666 Buffer
00667 Generator::
00668 drawSine2(
00669     const float64 & duration,
00670     const Buffer &  frequency,
00671     const Buffer &  phase)
00672 {
00673     if(duration <= 0.0) return Buffer();
00674 
00675     t_ = 0.0;
00676 
00677     Buffer y;
00678 
00679     uint64 n_samples = static_cast<uint64>(duration * sample_rate_ + 0.5);
00680 
00681     Buffer::circular_iterator f = frequency.cbegin();
00682     Buffer::circular_iterator p = phase.cbegin();
00683 
00684     for(uint64 i = 0; i < n_samples; ++i)
00685     {
00686         y << drawSine2(*f, *p);
00687         ++f;
00688         ++p;
00689     }
00690 
00691     return y;
00692 }
00693 
00695 Buffer
00696 Generator::
00697 drawSine2(
00698     const float64 & duration,
00699     const Buffer &  frequency,
00700     const float64 & phase)
00701 {
00702     Buffer p(1);
00703     p << phase;
00704 
00705     return drawSine2(duration, frequency, p);
00706 }
00707 
00709 Buffer
00710 Generator::
00711 drawSine2(
00712     const float64 & duration,
00713     const float64 & frequency,
00714     const Buffer &  phase)
00715 {
00716     Buffer f(1);
00717     f << frequency;
00718 
00719     return drawSine2(duration, f, phase);
00720 }
00721 
00723 float64
00724 Generator::
00725 drawSine2(const float64 & frequency, const float64 & phase)
00726 {
00727     float64 f = 0.0;
00728     float64 sample = 0.0;
00729 
00730     if(chorus_is_on_)
00731     {
00732         for(uint32 i = 0; i < chorus_n_voices_; ++i)
00733         {
00734             f = M_2PI * chorus_position_[i] * sample_time_ + M_PI * phase;
00735             sample += ::sin(f);
00736             chorus_position_[i] += frequency * chorus_factor_[i];
00737         }
00738         sample /= static_cast<float64>(chorus_n_voices_);
00739     }
00740     else
00741     {
00742         sample = ::sin(M_2PI * t_ * sample_time_ + M_PI * phase);
00743         t_ += frequency;
00744     }
00745 
00746     return sample;
00747 }
00748 
00750 float64
00751 Generator::
00752 drawSine(const float64 & frequency)
00753 {
00754     return drawSine2(frequency, 0.0);
00755 }
00756 
00757 
00759 Buffer
00760 Generator::
00761 drawWindow(const float64 & duration, WindowType type) const
00762 {
00763     switch(type)
00764     {
00765         case BARTLETT:        return drawWindowBartlett(duration);
00766         case BLACKMAN:        return drawWindowBlackman(duration);
00767         case BLACKMAN_HARRIS: return drawWindowBlackmanHarris(duration);
00768         case GAUSSIAN:        return drawGaussian(duration, duration/2.0, 1.0);
00769         case GAUSSIAN_05:     return drawFatGaussian(duration, 0.05);
00770         case GAUSSIAN_10:     return drawFatGaussian(duration, 0.10);
00771         case GAUSSIAN_15:     return drawFatGaussian(duration, 0.15);
00772         case GAUSSIAN_20:     return drawFatGaussian(duration, 0.20);
00773         case GAUSSIAN_25:     return drawFatGaussian(duration, 0.25);
00774         case GAUSSIAN_30:     return drawFatGaussian(duration, 0.30);
00775         case GAUSSIAN_33:     return drawFatGaussian(duration, 0.3333);
00776         case GAUSSIAN_35:     return drawFatGaussian(duration, 0.35);
00777         case GAUSSIAN_40:     return drawFatGaussian(duration, 0.40);
00778         case GAUSSIAN_45:     return drawFatGaussian(duration, 0.45);
00779         case GAUSSIAN_50:     return drawFatGaussian(duration, 0.50);
00780         case GAUSSIAN_55:     return drawFatGaussian(duration, 0.55);
00781         case GAUSSIAN_60:     return drawFatGaussian(duration, 0.60);
00782         case GAUSSIAN_65:     return drawFatGaussian(duration, 0.65);
00783         case GAUSSIAN_66:     return drawFatGaussian(duration, 0.6666);
00784         case GAUSSIAN_70:     return drawFatGaussian(duration, 0.70);
00785         case GAUSSIAN_75:     return drawFatGaussian(duration, 0.75);
00786         case GAUSSIAN_80:     return drawFatGaussian(duration, 0.80);
00787         case GAUSSIAN_85:     return drawFatGaussian(duration, 0.85);
00788         case GAUSSIAN_90:     return drawFatGaussian(duration, 0.90);
00789         case GAUSSIAN_95:     return drawFatGaussian(duration, 0.95);
00790         case GAUSSIAN_99:     return drawFatGaussian(duration, 0.9999);
00791         case HAMMING:         return drawWindowHamming(duration);
00792         case HANNING:         return drawWindowHanning(duration);
00793         case KAISER:          return drawWindowKaiser(duration);
00794         case NUTTALL:         return drawWindowNuttall(duration);
00795         case PARZEN:          return drawWindowParzen(duration);
00796         case RECTANGULAR:     return drawWindowRectangular(duration);
00797     }
00798 
00799     return drawWindowRectangular(duration);
00800 }
00801 
00803 static
00804 void
00805 cosinewindow(
00806     Buffer & win,
00807     const float64 & a0,
00808     const float64 & a1,
00809     const float64 & a2,
00810     const float64 & a3)
00811 {
00812     int32 n = win.getLength();
00813     for(int32 i = 0; i < n; ++i)
00814     {
00815         win[i] *= a0
00816                 - a1 * ::cos(2.0 * M_PI * i / n)
00817                 + a2 * ::cos(4.0 * M_PI * i / n)
00818                 - a3 * ::cos(6.0 * M_PI * i / n);
00819     }
00820 }
00821 
00823 Buffer
00824 Generator::
00825 drawWindowBartlett(const float64 & duration) const
00826 {
00827     Buffer window = drawLine(duration, 1.0, 1.0);
00828 
00829     int32 n = static_cast<int32>(duration * sample_rate_);
00830 
00831     float64 n_over_2 = static_cast<float64>(n / 2);
00832 
00833     for(int32 i = 0; i < n / 2; ++i)
00834     {
00835         float64 t = static_cast<float64>(i) / n_over_2;
00836         window[i] *= t;
00837         window[i + n/2] *= 1.0 - t;
00838     }
00839 
00840     return window;
00841 }
00842 
00844 Buffer
00845 Generator::
00846 drawWindowBlackman(const float64 & duration) const
00847 {
00848     Buffer window = drawLine(duration, 1.0, 1.0);
00849 
00850     cosinewindow(window, 0.42, 0.50, 0.08, 0.00);
00851 
00852     return window;
00853 }
00854 
00856 Buffer
00857 Generator::
00858 drawWindowBlackmanHarris(const float64 & duration) const
00859 {
00860     Buffer window = drawLine(duration, 1.0, 1.0);
00861 
00862     cosinewindow(window, 0.35875, 0.48829, 0.14128, 0.01168);
00863 
00864     return window;
00865 }
00866 
00867 
00869 Buffer
00870 Generator::
00871 drawWindowHamming(const float64 & duration) const
00872 {
00873     Buffer window = drawLine(duration, 1.0, 1.0);
00874 
00875     cosinewindow(window, 0.54, 0.46, 0.00, 0.00);
00876 
00877     return window;
00878 }
00879 
00881 Buffer
00882 Generator::
00883 drawWindowHanning(const float64 & duration) const
00884 {
00885     Buffer window = drawLine(duration, 1.0, 1.0);
00886 
00887     cosinewindow(window, 0.50, 0.50, 0.00, 0.00);
00888 
00889     return window;
00890 }
00891 
00893 // Computation of the modified Bessel function I_0(x) for any real x.
00894 //
00895 // The algorithm is based on the article by Abramowitz and Stegun [1]
00896 // as denoted in Numerical Recipes 2nd ed. on p. 230 (W.H.Press et al.).
00897 //
00898 // [1] M.Abramowitz and I.A.Stegun, Handbook of Mathematical Functions,
00899 //     Applied Mathematics Series vol. 55 (1964), Washington.
00900 //
00901 float64
00902 bessel_i0(const float64 & x)
00903 {
00904     const float64 p1 = 1.0,
00905                   p2 = 3.5156229,
00906                   p3 = 3.0899424,
00907                   p4 = 1.2067492,
00908                   p5 = 0.2659732,
00909                   p6 = 3.60768e-2,
00910                   p7 = 4.5813e-3;
00911 
00912     const float64 q1 =  0.39894228,
00913                   q2 =  1.328592e-2,
00914                   q3 =  2.25319e-3,
00915                   q4 = -1.57565e-3,
00916                   q5 =  9.16281e-3,
00917                   q6 = -2.057706e-2,
00918                   q7 =  2.635537e-2,
00919                   q8 = -1.647633e-2,
00920                   q9 =  3.92377e-3;
00921 
00922     float64 ax = ::fabs(x);
00923 
00924     float64      y = 0.0,
00925             result = 0.0;
00926 
00927     if (ax < 3.75)
00928     {
00929         y = ::pow(x / 3.75, 2);
00930         result = p1+y*(p2+y*(p3+y*(p4+y*(p5+y*(p6+y*p7)))));
00931     }
00932     else
00933     {
00934         y = 3.75 / ax;
00935         result = (::exp(ax) / ::sqrt(ax))
00936                * (q1+y*(q2+y*(q3+y*(q4+y*(q5+y*(q6+y*(q7+y*(q8+y*q9))))))));
00937  }
00938     return result;
00939 }
00940 
00941 
00943 Buffer
00944 Generator::
00945 drawWindowKaiser(const float64 & duration, const float64 & beta) const
00946 {
00947     Buffer window = drawLine(duration, 0.0, 0.0);
00948 
00949     int32 n_samples = window.getLength();
00950     float64 f_n_samples = float64(n_samples);
00951 
00952     float64 b = ::fabs(beta);
00953 
00954     if(b < 1.0)
00955     {
00956         b = 1.0;
00957     }
00958 
00960     // Calculate window coefficients
00961     //
00962     // alpha = n_samples / 2
00963     //
00964     // for n = 0 : n_samples -1
00965     //
00966     //     w[n] = bessel_i0( beta * sqrt(1.0 - [(n - alpha)/alpha]^2)
00967     //          / bessel_i0(beta)
00968     //
00969     //
00970 
00971     float64 alpha = f_n_samples / 2.0;
00972 
00973     float64 denominator = bessel_i0(b);
00974 
00975     for(int32 i = 0 ; i < n_samples; ++i)
00976     {
00977         float64 temp = (float64(i) - alpha) / alpha;
00978         temp *= temp;
00979 
00980         window[i] = bessel_i0( b * ::sqrt(1.0 - temp)) / denominator;
00981     }
00982 
00983     return window;
00984 }
00985 
00987 Buffer
00988 Generator::
00989 drawWindowNuttall(const float64 & duration) const
00990 {
00991     Buffer window = drawLine(duration, 1.0, 1.0);
00992 
00993     cosinewindow(window, 0.3635819, 0.4891775, 0.1365995, 0.0106411);
00994 
00995     return window;
00996 }
00997 
00999 Buffer
01000 Generator::
01001 drawWindowParzen(const float64 & duration) const
01002 {
01003     Buffer window = drawLine(duration, 1.0, 1.0);
01004 
01005     int32 n = static_cast<int32>(duration * sample_rate_);
01006 
01007     int32 N = n -1;
01008 
01009     float64 Nf = static_cast<float64>(N);
01010 
01011     for(int32 i = 0; i < N / 4; ++i)
01012     {
01013         float64 m = 2 * ::pow(1.0 - (Nf / 2 - i) / (Nf / 2), 3.0);
01014         window[i] *= m;
01015         window[N - i] *= m;
01016     }
01017 
01018     for(int32 i = N/4; i <= N/2; ++i)
01019     {
01020         int32 wn = i - N/2;
01021         float64 m = 1.0
01022                   - 6.0 * ::pow(wn / (Nf/2),2.0)
01023                       * (1.0 - ::fabs(wn) / (Nf/2));
01024 
01025         window[i] *= m;
01026         window[N-i] *= m;
01027     }
01028 
01029     return window;
01030 }
01031 
01033 Buffer
01034 Generator::
01035 drawWindowRectangular(const float64 & duration) const
01036 {
01037     return drawLine(duration, 1.0, 1.0);
01038 }
01039 
01041 float64
01042 Generator::
01043 generate(const float64 & frequency)
01044 {
01045     return generate2(frequency, 0.0);
01046 }
01047 
01049 float64
01050 Generator::
01051 generate2(const float64 & frequency, const float64 & phase)
01052 {
01053     if(waveform_ == NULL) return 0.0;
01054 
01055     ++sync_count_;
01056 
01057     if(sync_is_slave_ && !sync_vector_.empty())
01058     {
01059         uint32 sync_count = sync_vector_.front();
01060 
01061         if(sync_count_ == sync_count)
01062         {
01063             sync_vector_.erase(sync_vector_.begin());
01064             position_ = 0;
01065         }
01066     }
01067 
01068     // Move with phase
01069     float64 ph = (phase * sample_rate_ / 2.0);
01070     float64 position2 = position_ + ph + 0.5;
01071 
01072     // Range checks
01073     while(position2 >= sample_rate_)
01074     {
01075         position2 -= sample_rate_;
01076     }
01077 
01078     while(position2 < 0.0)
01079     {
01080         position2 += sample_rate_;
01081     }
01082 
01083     float64 sample = 0.0;
01084 
01085     if(chorus_is_on_)
01086     {
01087         for(uint32 i = 0; i < chorus_n_voices_; ++i)
01088         {
01089             float64 pos = chorus_position_[i]
01090                         + chorus_factor_[i] * frequency
01091                         + ph
01092                         + 0.5;
01093 
01094             // Range check
01095             while(pos >= sample_rate_) pos -= sample_rate_;
01096             while(pos <  0)            pos += sample_rate_;
01097 
01098             sample += (*waveform_)[static_cast<uint64>(pos)];
01099 
01100             chorus_position_[i] += frequency * chorus_factor_[i];
01101         }
01102 
01103         sample /= static_cast<float64>(chorus_n_voices_);
01104     }
01105     else
01106     {
01107         sample = (*waveform_)[static_cast<uint64>(position2)];
01108     }
01109 
01110     position_ += frequency;
01111 
01112     return sample;
01113 }
01114 
01116 Buffer
01117 Generator::
01118 generate(
01119     const float64 & duration,
01120     const float64 & frequency,
01121     bool reset_first)
01122 {
01123     if(duration <= 0.0) return Buffer();
01124 
01125     if(reset_first)
01126     {
01127         reset();
01128     }
01129 
01130     Buffer buffer;
01131 
01132     uint64 n_samples = static_cast<uint64>(std::ceil(duration * sample_rate_));
01133 
01134     for(uint64 i = 0; i < n_samples; ++i)
01135     {
01136         buffer << generate(frequency);
01137     }
01138 
01139     return buffer;
01140 }
01141 
01143 Buffer
01144 Generator::
01145 generate2(
01146     const float64 & duration,
01147     const float64 & frequency,
01148     const float64 & phase,
01149     bool reset_first)
01150 {
01151     if(duration <= 0.0) return Buffer();
01152 
01153     if(reset_first)
01154     {
01155         reset();
01156     }
01157 
01158     Buffer buffer;
01159 
01160     uint64 n_samples = static_cast<uint64>(std::ceil(duration * sample_rate_));
01161 
01162     for(uint64 i = 0; i < n_samples; ++i)
01163     {
01164         buffer << generate2(frequency, phase);
01165     }
01166 
01167     return buffer;
01168 }
01169 
01171 Buffer
01172 Generator::
01173 generate(
01174     const float64 & duration,
01175     const Buffer &  frequencies,
01176     bool reset_first)
01177 {
01178     if(duration <= 0.0) return Buffer();
01179 
01180     if(reset_first)
01181     {
01182         reset();
01183     }
01184 
01185     uint64 n_samples = static_cast<uint64>(std::ceil(duration * sample_rate_));
01186 
01187     Buffer y(n_samples);
01188 
01189     Buffer::circular_iterator freq = frequencies.cbegin();
01190 
01191     for(uint64 i = 0; i < n_samples; ++i, ++freq)
01192     {
01193         y << generate(*freq);
01194     }
01195 
01196     return y;
01197 }
01198 
01200 Buffer
01201 Generator::
01202 generate2(
01203     const float64 & duration,
01204     const float64 & frequency,
01205     const Buffer &  phase,
01206     bool reset_first)
01207 {
01208     if(duration <= 0.0) return Buffer();
01209 
01210     if(reset_first)
01211     {
01212         reset();
01213     }
01214 
01215     uint64 n_samples = static_cast<uint64>(std::ceil(duration * sample_rate_));
01216 
01217     Buffer y(n_samples);
01218 
01219     Buffer::circular_iterator p = phase.cbegin();
01220 
01221     for(uint64 i = 0; i < n_samples; ++i, ++p)
01222     {
01223         y << generate2(frequency,*p);
01224     }
01225 
01226     return y;
01227 }
01228 
01230 Buffer
01231 Generator::
01232 generate2(
01233     const float64 & duration,
01234     const Buffer &  frequencies,
01235     const float64 & phase,
01236     bool reset_first)
01237 {
01238     if(duration <= 0.0) return Buffer();
01239 
01240     if(reset_first)
01241     {
01242         reset();
01243     }
01244 
01245     uint64 n_samples = static_cast<uint64>(std::ceil(duration * sample_rate_));
01246 
01247     Buffer y(n_samples);
01248 
01249     Buffer::circular_iterator f = frequencies.cbegin();
01250 
01251     for(uint64 i = 0; i < n_samples; ++i, ++f)
01252     {
01253         y << generate2(*f, phase);
01254     }
01255 
01256     return y;
01257 }
01258 
01260 Buffer
01261 Generator::
01262 generate2(
01263     const float64 & duration,
01264     const Buffer &  frequencies,
01265     const Buffer &  phase,
01266     bool reset_first)
01267 {
01268     if(duration <= 0.0) return Buffer();
01269 
01270     if(reset_first)
01271     {
01272         reset();
01273     }
01274 
01275     uint64 n_samples = static_cast<uint64>(std::ceil(duration * sample_rate_));
01276 
01277     Buffer y(n_samples);
01278 
01279     Buffer::circular_iterator f = frequencies.cbegin();
01280     Buffer::circular_iterator p = phase.cbegin();
01281 
01282     for(uint64 i = 0; i < n_samples; ++i, ++f, ++p)
01283     {
01284         y << generate2(*f,*p);
01285     }
01286 
01287     return y;
01288 }
01289 
01291 Generator &
01292 Generator::
01293 operator=(const Generator & rhs)
01294 {
01295     // If this is the same object, return it.
01296     if(this == &rhs)
01297     {
01298         return *this;
01299     }
01300 
01301     last_frequency_ = rhs.last_frequency_;
01302     position_       = rhs.position_;
01303     sample_rate_    = rhs.sample_rate_;
01304     sample_time_    = rhs.sample_time_;
01305     t_              = rhs.t_;
01306 
01307     if(waveform_ != NULL && rhs.waveform_ != NULL)
01308     {
01309         *waveform_       = *rhs.waveform_;
01310     }
01311     else if(waveform_ == NULL && rhs.waveform_ != NULL)
01312     {
01313         waveform_ = new Buffer(*rhs.waveform_);
01314     }
01315     else if(waveform_ != NULL && rhs.waveform_ == NULL)
01316     {
01317         delete waveform_;
01318         waveform_ = NULL;
01319     }
01320 
01321     *rng_ = *rhs.rng_;
01322 
01323     buzz_max_harmonics_ = rhs.buzz_max_harmonics_;
01324     buzz_position_      = rhs.buzz_position_;
01325 
01326     chorus_is_on_    = rhs.chorus_is_on_;
01327     chorus_n_voices_ = rhs.chorus_n_voices_;
01328     chorus_position_ = rhs.chorus_position_;
01329     chorus_factor_   = rhs.chorus_factor_;
01330 
01331     sync_is_master_ = rhs.sync_is_master_;
01332     sync_is_slave_  = rhs.sync_is_slave_;
01333     sync_count_     = rhs.sync_count_;
01334     sync_vector_    = rhs.sync_vector_;
01335     sync_slaves_    = rhs.sync_slaves_;
01336 
01337     return *this;
01338 }
01339 
01341 void
01342 Generator::
01343 removeSlaveSync(Generator & slave)
01344 {
01345     slave.sync_is_slave_ = false;
01346 
01347     std::vector<Generator *>::iterator itor = sync_slaves_.begin();
01348     std::vector<Generator *>::iterator end = sync_slaves_.end();
01349 
01350     while(*itor != (&slave))
01351     {
01352         ++itor;
01353     }
01354 
01355     if(*itor == (&slave))
01356     {
01357         sync_slaves_.erase(itor);
01358     }
01359 
01360     reset();
01361 }
01362 
01363 
01365 void
01366 Generator::
01367 reset()
01368 {
01369     position_ = 0.0;
01370     last_frequency_ = -1.0;
01371     sync_count_ = 0;
01372     t_ = 0.0;
01373 
01374     buzz_position_.reserve(buzz_max_harmonics_);
01375 
01376     for(uint32 i = 0; i < buzz_max_harmonics_; ++i)
01377     {
01378         buzz_position_[i] = 0.0;
01379     }
01380 
01381     for(uint32 i = 0; i < chorus_n_voices_; ++i)
01382     {
01383         chorus_position_[i] = 0.0;
01384     }
01385 
01386     for(uint32 i = 0; i < sync_slaves_.size(); ++i)
01387     {
01388         sync_slaves_[i]->sync_vector_.clear();
01389     }
01390 }
01391 
01393 void
01394 Generator::
01395 setSeed(const uint32 seed)
01396 {
01397     rng_->setSeed(seed);
01398 }
01399 
01401 Buffer
01402 Generator::
01403 silence(const float64 & duration) const
01404 {
01405     if(duration <= 0.0) return Buffer();
01406 
01407     return drawLine(duration,0.0,0.0);
01408 }
01409 
01411 float64
01412 Generator::
01413 tell() const
01414 {
01415     return position_ / sample_rate_;
01416 }
01417 
01418 
01420 Buffer
01421 Generator::
01422 whiteNoise(const float64 & duration) const
01423 {
01424     if(duration <= 0.0) return Buffer();
01425 
01426     Buffer buffer;
01427 
01428     uint64 n_samples = static_cast<uint64>(std::ceil(duration * sample_rate_));
01429 
01430     for(uint64 i = 0; i < n_samples; ++i)
01431     {
01432         buffer << rng_->get(-1.0f,1.0f);
01433     }
01434 
01435     return buffer;
01436 }
01437 
01439 Buffer
01440 Generator::
01441 gaussianNoise(
01442     const float64 & duration,
01443     const float64 & mu,
01444     const float64 & sigma) const
01445 {
01446     if(duration <= 0.0) return Buffer();
01447 
01448     Buffer buffer;
01449 
01450     uint32 n_samples = static_cast<uint32>(std::ceil(duration * sample_rate_));
01451 
01452     // The polar form of the Box-Muller transformation.
01453 
01454     uint32 i = 0;
01455     while(true)
01456     {
01457         float64 f = 0.0;
01458         float64 x1 = 0.0;
01459         float64 x2 = 0.0;
01460         float64 r2 = 0.0;
01461 
01462         while(r2 == 0.0 || r2 >= 1.0)
01463         {
01464             x1 = rng_->get(-1.0f, 1.0f);
01465             x2 = rng_->get(-1.0f, 1.0f);
01466             r2 = x1 * x1 + x2 * x2;
01467         }
01468 
01469         f = ::sqrt(-2.0 * ::log(r2) / r2);
01470 
01471         buffer << mu + sigma * f * x1;
01472 
01473         ++i;
01474 
01475         if(i >= n_samples)
01476         {
01477             break;
01478         }
01479 
01480         buffer << mu + sigma * f * x2;
01481 
01482         ++i;
01483 
01484         if(i >= n_samples)
01485         {
01486             break;
01487         }
01488     }
01489 
01490     return buffer;
01491 }
01492 
01494 Buffer
01495 Generator::
01496 tanh(const float64 & duration) const
01497 {
01498     if(duration <= 0.0) return Buffer();
01499 
01500     Buffer buffer;
01501 
01502     uint64 n_samples = static_cast<uint64>(std::ceil(duration * sample_rate_));
01503 
01504     float64 step = (2.0 * M_PI) / n_samples;
01505 
01506     float64 x = -1.0 * M_PI;
01507 
01508     for(uint64 i = 0; i < n_samples; ++i)
01509     {
01510         buffer << std::tanh(x);
01511         x += step;
01512     }
01513 
01514     return buffer;
01515 }
Generated on Sun Apr 15 20:10:05 2012 for nsound by  doxygen 1.6.3