/* * oscillator.h - header-file for oscillator.cpp, a powerful oscillator-class * * Copyright (c) 2004-2008 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program (see COPYING); if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA. * */ #ifndef _OSCILLATOR_H #define _OSCILLATOR_H #include "lmmsconfig.h" #include #ifdef LMMS_HAVE_STDLIB_H #include #endif #include "sample_buffer.h" #include "lmms_constants.h" class sampleBuffer; class intModel; class EXPORT oscillator { public: enum WaveShapes { SineWave, TriangleWave, SawWave, SquareWave, MoogSawWave, ExponentialWave, WhiteNoise, UserDefinedWave, NumWaveShapes } ; enum ModulationAlgos { PhaseModulation, AmplitudeModulation, SignalMix, SynchronizedBySubOsc, FrequencyModulation, NumModulationAlgos } ; oscillator( const intModel * _wave_shape_model, const intModel * _mod_algo_model, const float & _freq, const float & _detuning, const float & _phase_offset, const float & _volume, oscillator * _m_subOsc = NULL ); virtual ~oscillator() { delete m_subOsc; } inline void setUserWave( const sampleBuffer * _wave ) { m_userWave = _wave; } void update( sampleFrame * _ab, const fpp_t _frames, const ch_cnt_t _chnl ); // now follow the wave-shape-routines... static inline sample_t sinSample( const float _sample ) { return( sinf( _sample * F_2PI ) ); } static inline sample_t triangleSample( const float _sample ) { const float ph = fraction( _sample ); if( ph <= 0.25f ) { return( ph * 4.0f ); } else if( ph <= 0.75f ) { return( 2.0f - ph * 4.0f ); } return( ph * 4.0f - 4.0f ); } static inline sample_t sawSample( const float _sample ) { return( -1.0f + fraction( _sample ) * 2.0f ); } static inline sample_t squareSample( const float _sample ) { return( ( fraction( _sample ) > 0.5f ) ? -1.0f : 1.0f ); } static inline sample_t moogSawSample( const float _sample ) { const float ph = fraction( _sample ); if( ph < 0.5f ) { return( -1.0f + ph * 4.0f ); } return( 1.0f - 2.0f * ph ); } static inline sample_t expSample( const float _sample ) { float ph = fraction( _sample ); if( ph > 0.5f ) { ph = 1.0f - ph; } return( -1.0f + 8.0f * ph * ph ); } static inline sample_t noiseSample( const float ) { // Precise implementation // return( 1.0f - rand() * 2.0f / RAND_MAX ); // Fast implementation return( 1.0f - fast_rand() * 2.0f / FAST_RAND_MAX ); } inline sample_t userWaveSample( const float _sample ) const { return( m_userWave->userWaveSample( _sample ) ); } private: const intModel * m_waveShapeModel; const intModel * m_modulationAlgoModel; const float & m_freq; const float & m_detuning; const float & m_volume; const float & m_ext_phaseOffset; oscillator * m_subOsc; float m_phaseOffset; float m_phase; const sampleBuffer * m_userWave; void updateNoSub( sampleFrame * _ab, const fpp_t _frames, const ch_cnt_t _chnl ); void updatePM( sampleFrame * _ab, const fpp_t _frames, const ch_cnt_t _chnl ); void updateAM( sampleFrame * _ab, const fpp_t _frames, const ch_cnt_t _chnl ); void updateMix( sampleFrame * _ab, const fpp_t _frames, const ch_cnt_t _chnl ); void updateSync( sampleFrame * _ab, const fpp_t _frames, const ch_cnt_t _chnl ); void updateFM( sampleFrame * _ab, const fpp_t _frames, const ch_cnt_t _chnl ); float syncInit( sampleFrame * _ab, const fpp_t _frames, const ch_cnt_t _chnl ); inline bool syncOk( float _osc_coeff ); template void updateNoSub( sampleFrame * _ab, const fpp_t _frames, const ch_cnt_t _chnl ); template void updatePM( sampleFrame * _ab, const fpp_t _frames, const ch_cnt_t _chnl ); template void updateAM( sampleFrame * _ab, const fpp_t _frames, const ch_cnt_t _chnl ); template void updateMix( sampleFrame * _ab, const fpp_t _frames, const ch_cnt_t _chnl ); template void updateSync( sampleFrame * _ab, const fpp_t _frames, const ch_cnt_t _chnl ); template void updateFM( sampleFrame * _ab, const fpp_t _frames, const ch_cnt_t _chnl ); template inline sample_t getSample( const float _sample ); inline void recalcPhase( void ); } ; #endif