annotate audio/ContinuousSynth.cpp @ 725:16f6737fa557 spectrogram-export

Rework OSC handler so as to consume all available messages rather than having to wait for the timeout in between them. Pause to process events, and also wait for file loads and transforms to complete. (Should only certain kinds of OSC command wait for transforms?)
author Chris Cannam
date Wed, 08 Jan 2020 15:33:17 +0000
parents 56acd9368532
children
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
Chris@436 22 ContinuousSynth::ContinuousSynth(int channels, sv_samplerate_t sampleRate, sv_frame_t blockSize, int waveType) :
Chris@313 23 m_channels(channels),
Chris@313 24 m_sampleRate(sampleRate),
Chris@313 25 m_blockSize(blockSize),
Chris@436 26 m_prevF0(-1.0),
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@436 43 ContinuousSynth::mix(float **toBuffers, float gain, float pan, float f0f)
Chris@313 44 {
Chris@436 45 double f0(f0f);
Chris@436 46 if (f0 == 0.0) f0 = m_prevF0;
Chris@313 47
Chris@436 48 bool wasOn = (m_prevF0 > 0.0);
Chris@436 49 bool nowOn = (f0 > 0.0);
Chris@313 50
Chris@313 51 if (!nowOn && !wasOn) {
Chris@436 52 m_phase = 0;
Chris@436 53 return;
Chris@313 54 }
Chris@313 55
Chris@436 56 sv_frame_t fadeLength = 100;
Chris@313 57
Chris@313 58 float *levels = new float[m_channels];
Chris@313 59
Chris@313 60 for (int c = 0; c < m_channels; ++c) {
Chris@436 61 levels[c] = gain * 0.5f; // scale gain otherwise too loud compared to source
Chris@313 62 }
Chris@313 63 if (pan != 0.0 && m_channels == 2) {
Chris@436 64 levels[0] *= 1.0f - pan;
Chris@436 65 levels[1] *= pan + 1.0f;
Chris@313 66 }
Chris@313 67
Chris@315 68 // cerr << "ContinuousSynth::mix: f0 = " << f0 << " (from " << m_prevF0 << "), phase = " << m_phase << endl;
Chris@313 69
Chris@436 70 for (sv_frame_t i = 0; i < m_blockSize; ++i) {
Chris@313 71
Chris@315 72 double fHere = (nowOn ? f0 : m_prevF0);
Chris@315 73
Chris@315 74 if (wasOn && nowOn && (f0 != m_prevF0) && (i < fadeLength)) {
Chris@315 75 // interpolate the frequency shift
Chris@436 76 fHere = m_prevF0 + ((f0 - m_prevF0) * double(i)) / double(fadeLength);
Chris@315 77 }
Chris@315 78
Chris@315 79 double phasor = (fHere * 2 * M_PI) / m_sampleRate;
Chris@315 80
rmb456@323 81 m_phase = m_phase + phasor;
Chris@313 82
Chris@436 83 int harmonics = int((m_sampleRate / 4) / fHere - 1);
Chris@318 84 if (harmonics < 1) harmonics = 1;
Chris@313 85
justin@327 86 switch (m_wavetype) {
Chris@326 87 case 1:
Chris@326 88 harmonics = 1;
Chris@326 89 break;
Chris@326 90 case 2:
Chris@326 91 break;
Chris@326 92 case 3:
Chris@326 93 break;
Chris@326 94 default:
Chris@326 95 harmonics = 3;
Chris@326 96 break;
justin@327 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@436 132 v = v * (double(i) / double(fadeLength));
Chris@318 133 } else if (!nowOn) {
Chris@318 134 // fade out
Chris@318 135 if (i > fadeLength) v = 0;
Chris@436 136 else v = v * (1.0 - (double(i) / double(fadeLength)));
Chris@318 137 }
Chris@318 138
Chris@318 139 for (int c = 0; c < m_channels; ++c) {
Chris@436 140 toBuffers[c][i] += float(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