Chris@313: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@313: Chris@313: /* Chris@313: Sonic Visualiser Chris@313: An audio file viewer and annotation editor. Chris@313: Centre for Digital Music, Queen Mary, University of London. Chris@313: Chris@313: This program is free software; you can redistribute it and/or Chris@313: modify it under the terms of the GNU General Public License as Chris@313: published by the Free Software Foundation; either version 2 of the Chris@313: License, or (at your option) any later version. See the file Chris@313: COPYING included with this distribution for more information. Chris@313: */ Chris@313: Chris@313: #include "ContinuousSynth.h" Chris@313: Chris@313: #include "base/Debug.h" Chris@313: Chris@313: #include Chris@313: Chris@313: ContinuousSynth::ContinuousSynth(int channels, int sampleRate, int blockSize) : Chris@313: m_channels(channels), Chris@313: m_sampleRate(sampleRate), Chris@313: m_blockSize(blockSize), Chris@313: m_prevF0(-1.f), Chris@313: m_phase(0.0) Chris@313: { Chris@313: } Chris@313: Chris@313: ContinuousSynth::~ContinuousSynth() Chris@313: { Chris@313: } Chris@313: Chris@313: void Chris@313: ContinuousSynth::reset() Chris@313: { Chris@313: m_phase = 0; Chris@313: } Chris@313: Chris@313: void Chris@313: ContinuousSynth::mix(float **toBuffers, float gain, float pan, float f0) Chris@313: { Chris@313: if (f0 == 0.f) f0 = m_prevF0; Chris@313: Chris@313: bool wasOn = (m_prevF0 > 0.f); Chris@313: bool nowOn = (f0 > 0.f); Chris@313: Chris@313: if (!nowOn && !wasOn) { Chris@313: m_phase = 0; Chris@313: return; Chris@313: } Chris@313: Chris@313: int fadeLength = 20; // samples Chris@313: Chris@313: float *levels = new float[m_channels]; Chris@313: Chris@313: for (int c = 0; c < m_channels; ++c) { Chris@313: levels[c] = gain; Chris@313: } Chris@313: if (pan != 0.0 && m_channels == 2) { Chris@313: levels[0] *= 1.0 - pan; Chris@313: levels[1] *= pan + 1.0; Chris@313: } Chris@313: Chris@313: double phasor = (f0 * 2 * M_PI) / m_sampleRate; Chris@313: double p = m_phase; Chris@313: Chris@313: cerr << "ContinuousSynth::mix: f0 = " << f0 << " (from " << m_prevF0 << "), phase = " << m_phase << ", phasor = " << phasor << endl; Chris@313: Chris@313: for (int i = 0; i < m_blockSize; ++i) { Chris@313: Chris@313: p = m_phase + i * phasor; Chris@313: Chris@313: double v = sin(p); Chris@313: Chris@313: if (!wasOn && i < fadeLength) { // fade in Chris@313: v = v * (i / double(fadeLength)); Chris@313: } else if (!nowOn) { Chris@313: if (i > fadeLength) v = 0; Chris@313: else v = v * (1.0 - (i / double(fadeLength))); Chris@313: } Chris@313: Chris@313: for (int c = 0; c < m_channels; ++c) { Chris@313: toBuffers[c][i] += levels[c] * v; Chris@313: } Chris@313: } Chris@313: Chris@313: m_prevF0 = f0; Chris@313: m_phase = p; Chris@313: Chris@313: delete[] levels; Chris@313: } Chris@313: