Files
lmms/plugins/SpectrumAnalyzer/SpectrumAnalyzer.cpp
2017-11-22 11:08:47 +01:00

173 lines
3.8 KiB
C++

/*
* SpectrumAnalyzer.cpp - spectrum analyzer effect plugin
*
* Copyright (c) 2008-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of LMMS - https://lmms.io
*
* 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.
*
*/
#include "SpectrumAnalyzer.h"
#include "embed.h"
extern "C"
{
Plugin::Descriptor PLUGIN_EXPORT spectrumanalyzer_plugin_descriptor =
{
STRINGIFY( PLUGIN_NAME ),
"Spectrum Analyzer",
QT_TRANSLATE_NOOP( "pluginBrowser", "Graphical spectrum analyzer plugin" ),
"Tobias Doerffel <tobydox/at/users.sf.net>",
0x0100,
Plugin::Effect,
new PluginPixmapLoader(),
NULL,
NULL
} ;
}
SpectrumAnalyzer::SpectrumAnalyzer( Model * _parent,
const Descriptor::SubPluginFeatures::Key * _key ) :
Effect( &spectrumanalyzer_plugin_descriptor, _parent, _key ),
m_saControls( this ),
m_framesFilledUp( 0 ),
m_energy( 0 )
{
memset( m_buffer, 0, sizeof( m_buffer ) );
m_specBuf = (fftwf_complex *) fftwf_malloc( ( FFT_BUFFER_SIZE + 1 ) * sizeof( fftwf_complex ) );
m_fftPlan = fftwf_plan_dft_r2c_1d( FFT_BUFFER_SIZE*2, m_buffer, m_specBuf, FFTW_MEASURE );
}
SpectrumAnalyzer::~SpectrumAnalyzer()
{
fftwf_destroy_plan( m_fftPlan );
fftwf_free( m_specBuf );
}
bool SpectrumAnalyzer::processAudioBuffer( sampleFrame* _buf, const fpp_t _frames )
{
if( !isEnabled() || !isRunning () )
{
return false;
}
if( !m_saControls.isViewVisible() )
{
return true;
}
fpp_t f = 0;
if( _frames > FFT_BUFFER_SIZE )
{
m_framesFilledUp = 0;
f = _frames - FFT_BUFFER_SIZE;
}
const int cm = m_saControls.m_channelMode.value();
switch( cm )
{
case MergeChannels:
for( ; f < _frames; ++f )
{
m_buffer[m_framesFilledUp] =
( _buf[f][0] + _buf[f][1] ) * 0.5;
++m_framesFilledUp;
}
break;
case LeftChannel:
for( ; f < _frames; ++f )
{
m_buffer[m_framesFilledUp] = _buf[f][0];
++m_framesFilledUp;
}
break;
case RightChannel:
for( ; f < _frames; ++f )
{
m_buffer[m_framesFilledUp] = _buf[f][1];
++m_framesFilledUp;
}
break;
}
if( m_framesFilledUp < FFT_BUFFER_SIZE )
{
return isRunning();
}
// hanming( m_buffer, FFT_BUFFER_SIZE, HAMMING );
const sample_rate_t sr = Engine::mixer()->processingSampleRate();
const int LOWEST_FREQ = 0;
const int HIGHEST_FREQ = sr / 2;
fftwf_execute( m_fftPlan );
absspec( m_specBuf, m_absSpecBuf, FFT_BUFFER_SIZE+1 );
if( m_saControls.m_linearSpec.value() )
{
compressbands( m_absSpecBuf, m_bands, FFT_BUFFER_SIZE+1,
MAX_BANDS,
(int)(LOWEST_FREQ*(FFT_BUFFER_SIZE+1)/(float)(sr/2)),
(int)(HIGHEST_FREQ*(FFT_BUFFER_SIZE+1)/(float)(sr/2)));
m_energy = maximum( m_bands, MAX_BANDS ) / maximum( m_buffer, FFT_BUFFER_SIZE );
}
else
{
calc13octaveband31( m_absSpecBuf, m_bands, FFT_BUFFER_SIZE+1, sr/2.0 );
m_energy = signalpower( m_buffer, FFT_BUFFER_SIZE ) / maximum( m_buffer, FFT_BUFFER_SIZE );
}
m_framesFilledUp = 0;
checkGate( 1 );
return isRunning();
}
extern "C"
{
// necessary for getting instance out of shared lib
PLUGIN_EXPORT Plugin * lmms_plugin_main( Model* parent, void* data )
{
return new SpectrumAnalyzer( parent, static_cast<const Plugin::Descriptor::SubPluginFeatures::Key *>( data ) );
}
}