From 1e77ddff85c2cd6ddc621d33f2b35dc1e1bea1ac Mon Sep 17 00:00:00 2001 From: Javier Serrano Polo Date: Fri, 9 Jun 2006 21:15:20 +0000 Subject: [PATCH] - reverted to PM and added FM as a new modulation method\n- improved performance, specially PM/FM\n- moved fraction() to global scope\n- removed absolute value from userWaveSample, it's handled by fraction() git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/trunk/lmms@150 0778d3d1-df1d-0410-868b-ea421aaaa00d --- include/lmms_math.h | 38 ++++++++++++++++++++++++++++++++++++++ include/oscillator.h | 12 +++++------- include/sample_buffer.h | 8 ++------ src/lib/oscillator.cpp | 39 ++++++++++++++++++++++++++++----------- 4 files changed, 73 insertions(+), 24 deletions(-) create mode 100644 include/lmms_math.h diff --git a/include/lmms_math.h b/include/lmms_math.h new file mode 100644 index 000000000..f54a3c196 --- /dev/null +++ b/include/lmms_math.h @@ -0,0 +1,38 @@ +/* + * lmms_math.h - defines math functions + * + * Copyright (c) 2004-2006 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +#ifndef _LMMS_MATH_H +#define _LMMS_MATH_H + + +// Equivalent to _x - floorf( _x ) +static inline float fraction( const float _x ) +{ + return( _x - ( _x >= 0.0f ? static_cast( _x ) : + static_cast( _x ) - 1 ) ); +} + + +#endif diff --git a/include/oscillator.h b/include/oscillator.h index eb4fbeb76..59749e613 100644 --- a/include/oscillator.h +++ b/include/oscillator.h @@ -37,6 +37,7 @@ #include "mixer.h" #include "sample_buffer.h" #include "lmms_constants.h" +#include "lmms_math.h" class oscillator @@ -56,7 +57,7 @@ public: enum modulationAlgos { - FREQ_MODULATION, AMP_MODULATION, MIX, SYNC + PHASE_MODULATION, AMP_MODULATION, MIX, SYNC, FREQ_MODULATION } ; oscillator( const waveShapes * _wave_shape, @@ -86,11 +87,6 @@ public: "fistpl %0\n" \ "shrl $1,%0" : "=m" (out) : "t" (in),"m"(round_const) : "st") ;*/ - static inline float fraction( const float _sample ) - { - return( _sample - static_cast( _sample ) ); - } - // now follow the wave-shape-routines... static inline sample_t sinSample( const float _sample ) @@ -176,7 +172,7 @@ private: void updateNoSub( sampleFrame * _ab, const fpab_t _frames, const ch_cnt_t _chnl ); - void updateFM( sampleFrame * _ab, const fpab_t _frames, + void updatePM( sampleFrame * _ab, const fpab_t _frames, const ch_cnt_t _chnl ); void updateAM( sampleFrame * _ab, const fpab_t _frames, const ch_cnt_t _chnl ); @@ -184,6 +180,8 @@ private: const ch_cnt_t _chnl ); void updateSync( sampleFrame * _ab, const fpab_t _frames, const ch_cnt_t _chnl ); + void updateFM( sampleFrame * _ab, const fpab_t _frames, + const ch_cnt_t _chnl ); float syncInit( sampleFrame * _ab, const fpab_t _frames, const ch_cnt_t _chnl ); diff --git a/include/sample_buffer.h b/include/sample_buffer.h index e313a5284..efbdf85b2 100644 --- a/include/sample_buffer.h +++ b/include/sample_buffer.h @@ -53,6 +53,7 @@ #include "mixer.h" #include "interpolation.h" #include "types.h" +#include "lmms_math.h" class QPainter; @@ -150,15 +151,10 @@ public: _dst_sr, _buf->eng() ) ); } - static inline float fraction( const float _sample ) - { - return( _sample - static_cast( _sample ) ); - } - inline sample_t userWaveSample( const float _sample ) { m_dataMutex.lock(); - const float frame = fraction( fabs( _sample ) ) * m_frames; + const float frame = fraction( _sample ) * m_frames; const f_cnt_t f1 = static_cast( frame ); const f_cnt_t f2 = ( f1 + 1 ) % m_frames; sample_t waveSample = linearInterpolate( m_data[f1][0], diff --git a/src/lib/oscillator.cpp b/src/lib/oscillator.cpp index 4b87d5dc0..6ed7f5986 100644 --- a/src/lib/oscillator.cpp +++ b/src/lib/oscillator.cpp @@ -58,8 +58,8 @@ void oscillator::update( sampleFrame * _ab, const fpab_t _frames, const ch_cnt_t { switch( *m_modulationAlgo ) { - case FREQ_MODULATION: - updateFM( _ab, _frames, _chnl ); + case PHASE_MODULATION: + updatePM( _ab, _frames, _chnl ); break; case AMP_MODULATION: updateAM( _ab, _frames, _chnl ); @@ -70,6 +70,8 @@ void oscillator::update( sampleFrame * _ab, const fpab_t _frames, const ch_cnt_t case SYNC: updateSync( _ab, _frames, _chnl ); break; + case FREQ_MODULATION: + updateFM( _ab, _frames, _chnl ); } } else @@ -96,8 +98,8 @@ void oscillator::updateNoSub( sampleFrame * _ab, const fpab_t _frames, } -// do fm by using sub-osc as modulator -void oscillator::updateFM( sampleFrame * _ab, const fpab_t _frames, +// do pm by using sub-osc as modulator +void oscillator::updatePM( sampleFrame * _ab, const fpab_t _frames, const ch_cnt_t _chnl ) { m_subOsc->update( _ab, _frames, _chnl ); @@ -106,12 +108,8 @@ void oscillator::updateFM( sampleFrame * _ab, const fpab_t _frames, for( fpab_t frame = 0; frame < _frames; ++frame ) { - m_phase += _ab[frame][_chnl]; - if ( m_phase < 0.0f ) - { - m_phase -= floorf(m_phase); - } - _ab[frame][_chnl] = getSample( m_phase ) * *m_volume; + _ab[frame][_chnl] = getSample( m_phase + _ab[frame][_chnl] ) + * *m_volume; m_phase += osc_coeff; } } @@ -172,6 +170,25 @@ void oscillator::updateSync( sampleFrame * _ab, const fpab_t _frames, +// do fm by using sub-osc as modulator +void oscillator::updateFM( sampleFrame * _ab, const fpab_t _frames, + const ch_cnt_t _chnl ) +{ + m_subOsc->update( _ab, _frames, _chnl ); + recalcPhase(); + float osc_coeff = *m_freq * *m_detuning; + + for( fpab_t frame = 0; frame < _frames; ++frame ) + { + m_phase += _ab[frame][_chnl]; + _ab[frame][_chnl] = getSample( m_phase ) * *m_volume; + m_phase += osc_coeff; + } +} + + + + inline sample_t oscillator::getSample( const float _sample ) { switch( *m_waveShape ) @@ -206,7 +223,7 @@ inline void oscillator::recalcPhase( void ) { if( m_phaseOffset != *m_ext_phaseOffset ) { - m_phase += 1.0f - m_phaseOffset; + m_phase -= m_phaseOffset; m_phaseOffset = *m_ext_phaseOffset; m_phase += m_phaseOffset; }