annotate audioio/ContinuousSynth.cpp @ 403:eb84b06301da

Restore the old prev/next layer commands (that were never enabled because they didn't work) using the new fixed order layer list (so they now do work)
author Chris Cannam
date Tue, 02 Sep 2014 16:06:41 +0100
parents d2c13ec0f148
children 8d2112977aa0 72c662fe7ea3
rev   line source
Chris@313 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@313 2
Chris@313 3 /*
Chris@313 4 Sonic Visualiser
Chris@313 5 An audio file viewer and annotation editor.
Chris@313 6 Centre for Digital Music, Queen Mary, University of London.
Chris@313 7
Chris@313 8 This program is free software; you can redistribute it and/or
Chris@313 9 modify it under the terms of the GNU General Public License as
Chris@313 10 published by the Free Software Foundation; either version 2 of the
Chris@313 11 License, or (at your option) any later version. See the file
Chris@313 12 COPYING included with this distribution for more information.
Chris@313 13 */
Chris@313 14
Chris@313 15 #include "ContinuousSynth.h"
Chris@313 16
Chris@313 17 #include "base/Debug.h"
Chris@318 18 #include "system/System.h"
Chris@313 19
Chris@313 20 #include <cmath>
Chris@313 21
rmb456@323 22 ContinuousSynth::ContinuousSynth(int channels, int sampleRate, int blockSize, int waveType) :
Chris@313 23 m_channels(channels),
Chris@313 24 m_sampleRate(sampleRate),
Chris@313 25 m_blockSize(blockSize),
Chris@313 26 m_prevF0(-1.f),
rmb456@323 27 m_phase(0.0),
Chris@326 28 m_wavetype(waveType) // 0: 3 sinusoids, 1: 1 sinusoid, 2: sawtooth, 3: square
Chris@313 29 {
Chris@313 30 }
Chris@313 31
Chris@313 32 ContinuousSynth::~ContinuousSynth()
Chris@313 33 {
Chris@313 34 }
Chris@313 35
Chris@313 36 void
Chris@313 37 ContinuousSynth::reset()
Chris@313 38 {
Chris@313 39 m_phase = 0;
Chris@313 40 }
Chris@313 41
Chris@313 42 void
Chris@313 43 ContinuousSynth::mix(float **toBuffers, float gain, float pan, float f0)
Chris@313 44 {
Chris@313 45 if (f0 == 0.f) f0 = m_prevF0;
Chris@313 46
Chris@313 47 bool wasOn = (m_prevF0 > 0.f);
Chris@313 48 bool nowOn = (f0 > 0.f);
Chris@313 49
Chris@313 50 if (!nowOn && !wasOn) {
justin@327 51 m_phase = 0;
justin@327 52 return;
Chris@313 53 }
Chris@313 54
Chris@315 55 int fadeLength = 100; // samples
Chris@313 56
Chris@313 57 float *levels = new float[m_channels];
Chris@313 58
Chris@313 59 for (int c = 0; c < m_channels; ++c) {
justin@327 60 levels[c] = gain * 0.5; // scale gain otherwise too loud compared to source
Chris@313 61 }
Chris@313 62 if (pan != 0.0 && m_channels == 2) {
justin@327 63 levels[0] *= 1.0 - pan;
justin@327 64 levels[1] *= pan + 1.0;
Chris@313 65 }
Chris@313 66
Chris@315 67 // cerr << "ContinuousSynth::mix: f0 = " << f0 << " (from " << m_prevF0 << "), phase = " << m_phase << endl;
Chris@313 68
Chris@313 69 for (int i = 0; i < m_blockSize; ++i) {
Chris@313 70
Chris@315 71 double fHere = (nowOn ? f0 : m_prevF0);
Chris@315 72
Chris@315 73 if (wasOn && nowOn && (f0 != m_prevF0) && (i < fadeLength)) {
Chris@315 74 // interpolate the frequency shift
Chris@315 75 fHere = m_prevF0 + ((f0 - m_prevF0) * i) / fadeLength;
Chris@315 76 }
Chris@315 77
Chris@315 78 double phasor = (fHere * 2 * M_PI) / m_sampleRate;
Chris@315 79
rmb456@323 80 m_phase = m_phase + phasor;
Chris@313 81
Chris@318 82 int harmonics = (m_sampleRate / 4) / fHere - 1;
Chris@318 83 if (harmonics < 1) harmonics = 1;
Chris@313 84
justin@327 85 switch (m_wavetype) {
Chris@326 86 case 1:
Chris@326 87 harmonics = 1;
Chris@326 88 break;
Chris@326 89 case 2:
Chris@326 90 break;
Chris@326 91 case 3:
Chris@326 92 break;
Chris@326 93 default:
Chris@326 94 harmonics = 3;
Chris@326 95 break;
justin@327 96 }
rmb456@323 97
rmb456@323 98
Chris@318 99 for (int h = 0; h < harmonics; ++h) {
rmb456@323 100
Chris@326 101 double v = 0;
Chris@326 102 double hn = 0;
Chris@326 103 double hp = 0;
rmb456@323 104
Chris@326 105 switch (m_wavetype) {
Chris@326 106 case 1: // single sinusoid
Chris@326 107 v = sin(m_phase);
Chris@326 108 break;
Chris@326 109 case 2: // sawtooth
Chris@326 110 if (h != 0) {
justin@325 111 hn = h + 1;
rmb456@323 112 hp = m_phase * hn;
Chris@326 113 v = -(1.0 / M_PI) * sin(hp) / hn;
Chris@326 114 } else {
Chris@326 115 v = 0.5;
Chris@326 116 }
Chris@326 117 break;
Chris@326 118 case 3: // square
Chris@326 119 hn = h*2 + 1;
Chris@326 120 hp = m_phase * hn;
Chris@326 121 v = sin(hp) / hn;
Chris@326 122 break;
Chris@326 123 default: // 3 sinusoids
Chris@326 124 hn = h + 1;
Chris@326 125 hp = m_phase * hn;
Chris@326 126 v = sin(hp) / hn;
Chris@326 127 break;
Chris@326 128 }
Chris@318 129
Chris@318 130 if (!wasOn && i < fadeLength) {
Chris@318 131 // fade in
Chris@318 132 v = v * (i / double(fadeLength));
Chris@318 133 } else if (!nowOn) {
Chris@318 134 // fade out
Chris@318 135 if (i > fadeLength) v = 0;
Chris@318 136 else v = v * (1.0 - (i / double(fadeLength)));
Chris@318 137 }
Chris@318 138
Chris@318 139 for (int c = 0; c < m_channels; ++c) {
Chris@318 140 toBuffers[c][i] += levels[c] * v;
Chris@318 141 }
Chris@318 142 }
justin@327 143 }
Chris@313 144
Chris@313 145 m_prevF0 = f0;
Chris@313 146
Chris@313 147 delete[] levels;
Chris@313 148 }
Chris@313 149