svapp
1.9
|
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ 00002 00003 /* 00004 Sonic Visualiser 00005 An audio file viewer and annotation editor. 00006 Centre for Digital Music, Queen Mary, University of London. 00007 00008 This program is free software; you can redistribute it and/or 00009 modify it under the terms of the GNU General Public License as 00010 published by the Free Software Foundation; either version 2 of the 00011 License, or (at your option) any later version. See the file 00012 COPYING included with this distribution for more information. 00013 */ 00014 00015 #include "ContinuousSynth.h" 00016 00017 #include "base/Debug.h" 00018 #include "system/System.h" 00019 00020 #include <cmath> 00021 00022 ContinuousSynth::ContinuousSynth(int channels, int sampleRate, int blockSize, int waveType) : 00023 m_channels(channels), 00024 m_sampleRate(sampleRate), 00025 m_blockSize(blockSize), 00026 m_prevF0(-1.f), 00027 m_phase(0.0), 00028 m_wavetype(waveType) // 0: 3 sinusoids, 1: 1 sinusoid, 2: sawtooth, 3: square 00029 { 00030 } 00031 00032 ContinuousSynth::~ContinuousSynth() 00033 { 00034 } 00035 00036 void 00037 ContinuousSynth::reset() 00038 { 00039 m_phase = 0; 00040 } 00041 00042 void 00043 ContinuousSynth::mix(float **toBuffers, float gain, float pan, float f0) 00044 { 00045 if (f0 == 0.f) f0 = m_prevF0; 00046 00047 bool wasOn = (m_prevF0 > 0.f); 00048 bool nowOn = (f0 > 0.f); 00049 00050 if (!nowOn && !wasOn) { 00051 m_phase = 0; 00052 return; 00053 } 00054 00055 int fadeLength = 100; // samples 00056 00057 float *levels = new float[m_channels]; 00058 00059 for (int c = 0; c < m_channels; ++c) { 00060 levels[c] = gain * 0.5; // scale gain otherwise too loud compared to source 00061 } 00062 if (pan != 0.0 && m_channels == 2) { 00063 levels[0] *= 1.0 - pan; 00064 levels[1] *= pan + 1.0; 00065 } 00066 00067 // cerr << "ContinuousSynth::mix: f0 = " << f0 << " (from " << m_prevF0 << "), phase = " << m_phase << endl; 00068 00069 for (int i = 0; i < m_blockSize; ++i) { 00070 00071 double fHere = (nowOn ? f0 : m_prevF0); 00072 00073 if (wasOn && nowOn && (f0 != m_prevF0) && (i < fadeLength)) { 00074 // interpolate the frequency shift 00075 fHere = m_prevF0 + ((f0 - m_prevF0) * i) / fadeLength; 00076 } 00077 00078 double phasor = (fHere * 2 * M_PI) / m_sampleRate; 00079 00080 m_phase = m_phase + phasor; 00081 00082 int harmonics = (m_sampleRate / 4) / fHere - 1; 00083 if (harmonics < 1) harmonics = 1; 00084 00085 switch (m_wavetype) { 00086 case 1: 00087 harmonics = 1; 00088 break; 00089 case 2: 00090 break; 00091 case 3: 00092 break; 00093 default: 00094 harmonics = 3; 00095 break; 00096 } 00097 00098 00099 for (int h = 0; h < harmonics; ++h) { 00100 00101 double v = 0; 00102 double hn = 0; 00103 double hp = 0; 00104 00105 switch (m_wavetype) { 00106 case 1: // single sinusoid 00107 v = sin(m_phase); 00108 break; 00109 case 2: // sawtooth 00110 if (h != 0) { 00111 hn = h + 1; 00112 hp = m_phase * hn; 00113 v = -(1.0 / M_PI) * sin(hp) / hn; 00114 } else { 00115 v = 0.5; 00116 } 00117 break; 00118 case 3: // square 00119 hn = h*2 + 1; 00120 hp = m_phase * hn; 00121 v = sin(hp) / hn; 00122 break; 00123 default: // 3 sinusoids 00124 hn = h + 1; 00125 hp = m_phase * hn; 00126 v = sin(hp) / hn; 00127 break; 00128 } 00129 00130 if (!wasOn && i < fadeLength) { 00131 // fade in 00132 v = v * (i / double(fadeLength)); 00133 } else if (!nowOn) { 00134 // fade out 00135 if (i > fadeLength) v = 0; 00136 else v = v * (1.0 - (i / double(fadeLength))); 00137 } 00138 00139 for (int c = 0; c < m_channels; ++c) { 00140 toBuffers[c][i] += levels[c] * v; 00141 } 00142 } 00143 } 00144 00145 m_prevF0 = f0; 00146 00147 delete[] levels; 00148 } 00149