Skip to content

Commit

Permalink
SampleBuffer: A few changes
Browse files Browse the repository at this point in the history
* Exporting and restoring is universally done now by saveSettings and
loadSettings. That's allows us to make sure we don't left any important
attributes like "sampleRate" behind.
* Don't use sharedObject. It does not make any sense and could lead to
bugs when allocated locally (see audio_file_processor). When needed,
this commit used std::shared_ptr which was made for that.
  • Loading branch information
Reflexe committed May 23, 2018
1 parent a170cb9 commit 84a1f35
Show file tree
Hide file tree
Showing 12 changed files with 115 additions and 85 deletions.
30 changes: 19 additions & 11 deletions include/SampleBuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "lmms_math.h"
#include "shared_object.h"
#include "MemoryManager.h"
#include "JournallingObject.h"


class QPainter;
Expand All @@ -50,7 +51,8 @@ class QRect;
// may need to be higher - conversely, to optimize, some may work with lower values
const f_cnt_t MARGIN[] = { 64, 64, 64, 4, 4 };

class EXPORT SampleBuffer : public QObject, public sharedObject
class EXPORT SampleBuffer : public QObject,
public JournallingObject
{
Q_OBJECT
MM_OPERATORS
Expand Down Expand Up @@ -106,13 +108,19 @@ class EXPORT SampleBuffer : public QObject, public sharedObject

} ;


SampleBuffer();
// constructor which either loads sample _audio_file or decodes
// base64-data out of string
SampleBuffer( const QString & _audio_file, bool _is_base64_data = false );
SampleBuffer(const QString & _audio_file, bool _is_base64_data, sample_rate_t sampleRate=0);
SampleBuffer(DataVector &&movedData, sample_rate_t sampleRate);

inline virtual QString nodeName() const override
{
return "samplebuffer";
}
virtual void saveSettings(QDomDocument& doc, QDomElement& _this ) override;
virtual void loadSettings(const QDomElement& _this ) override;

bool play( sampleFrame * _ab, handleState * _state,
const fpp_t _frames,
const float _freq,
Expand Down Expand Up @@ -197,11 +205,6 @@ class EXPORT SampleBuffer : public QObject, public sharedObject
m_frequency = _freq;
}

inline void setSampleRate( sample_rate_t _rate )
{
m_sampleRate = _rate;
}

inline const sampleFrame * data() const
{
return m_data.data ();
Expand All @@ -211,8 +214,6 @@ class EXPORT SampleBuffer : public QObject, public sharedObject
QString openAndSetAudioFile();
QString openAndSetWaveformFile();

QString & toBase64( QString & _dst ) const;

void normalizeSampleRate( const sample_rate_t _src_sr,
bool _keep_settings = false );

Expand Down Expand Up @@ -276,15 +277,22 @@ class EXPORT SampleBuffer : public QObject, public sharedObject
*/
void reverse(bool shouldLockMixer=true);

void loadFromBase64(const QString & _data , sample_rate_t sampleRate, bool shouldLock);

public slots:
void setAudioFile( const QString & _audio_file );
void loadFromBase64(const QString & _data , bool shouldLock);
void setStartFrame( const f_cnt_t _s );
void setEndFrame( const f_cnt_t _e );
void setAmplification( float _a );
void sampleRateChanged();

protected:
QString & toBase64( QString & _dst ) const;
inline void setSampleRate( sample_rate_t _rate )
{
m_sampleRate = _rate;
}

static sample_rate_t mixerSampleRate();

// HACK: libsamplerate < 0.1.8 doesn't get read-only variables
Expand Down
6 changes: 4 additions & 2 deletions include/SamplePlayHandle.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
#include "AutomatableModel.h"
#include "PlayHandle.h"

#include <memory>

class BBTrack;
class SampleTCO;
class Track;
Expand All @@ -38,7 +40,7 @@ class AudioPort;
class SamplePlayHandle : public PlayHandle
{
public:
SamplePlayHandle(SampleBuffer* sampleBuffer , bool shouldCreateAudioPort=true);
SamplePlayHandle(const std::shared_ptr<SampleBuffer> &sampleBuffer, bool shouldCreateAudioPort=true);
SamplePlayHandle( const QString& sampleFile );
SamplePlayHandle( SampleTCO* tco );
virtual ~SamplePlayHandle();
Expand Down Expand Up @@ -76,7 +78,7 @@ class SamplePlayHandle : public PlayHandle


private:
SampleBuffer * m_sampleBuffer;
std::shared_ptr<SampleBuffer> m_sampleBuffer;
bool m_doneMayReturnTrue;

f_cnt_t m_frame;
Expand Down
4 changes: 2 additions & 2 deletions include/SampleTrack.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class SampleTCO : public TrackContentObject
return "sampletco";
}

SampleBuffer* sampleBuffer()
const std::shared_ptr<SampleBuffer> sampleBuffer()
{
return m_sampleBuffer;
}
Expand Down Expand Up @@ -82,7 +82,7 @@ private slots:
void onSampleBufferChanged ();

private:
SampleBuffer* m_sampleBuffer;
std::shared_ptr<SampleBuffer> m_sampleBuffer;
BoolModel m_recordModel;
bool m_isPlaying;

Expand Down
17 changes: 8 additions & 9 deletions plugins/audio_file_processor/audio_file_processor.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*
/*
* audio_file_processor.cpp - instrument for using audio-files
*
* Copyright (c) 2004-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
Expand Down Expand Up @@ -210,13 +210,7 @@ void audioFileProcessor::deleteNotePluginData( NotePlayHandle * _n )
void audioFileProcessor::saveSettings( QDomDocument & _doc,
QDomElement & _this )
{
_this.setAttribute( "src", m_sampleBuffer.audioFile() );
if( m_sampleBuffer.audioFile() == "" )
{
QString s;
_this.setAttribute( "sampledata",
m_sampleBuffer.toBase64( s ) );
}
m_sampleBuffer.saveState (_doc, _this);
m_reverseModel.saveSettings( _doc, _this, "reversed" );
m_loopModel.saveSettings( _doc, _this, "looped" );
m_ampModel.saveSettings( _doc, _this, "amp" );
Expand Down Expand Up @@ -247,7 +241,12 @@ void audioFileProcessor::loadSettings( const QDomElement & _this )
}
else if( _this.attribute( "sampledata" ) != "" )
{
m_sampleBuffer.loadFromBase64( _this.attribute( "srcdata" ) , true);
m_sampleBuffer.loadFromBase64( _this.attribute( "srcdata" ) ,
true,
Engine::mixer ()->baseSampleRate ());
qWarning("Using default sampleRate. That could lead to invalid values");
} else {
m_sampleBuffer.restoreState (_this.firstChildElement (m_sampleBuffer.nodeName ()));
}

m_loopModel.loadSettings( _this, "looped" );
Expand Down
24 changes: 10 additions & 14 deletions plugins/patman/patman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ void patmanInstrument::playNote( NotePlayHandle * _n,
void patmanInstrument::deleteNotePluginData( NotePlayHandle * _n )
{
handle_data * hdata = (handle_data *)_n->m_pluginData;
sharedObject::unref( hdata->sample );

delete hdata->state;
delete hdata;
}
Expand Down Expand Up @@ -357,7 +357,7 @@ patmanInstrument::LoadErrors patmanInstrument::loadPatch(
}
}

SampleBuffer* psample = new SampleBuffer( std::move(data), sample_rate );
auto psample = std::make_shared<SampleBuffer>( std::move(data), sample_rate );
psample->setFrequency( root_freq / 1000.0f );

if( modes & MODES_LOOPING )
Expand All @@ -366,7 +366,7 @@ patmanInstrument::LoadErrors patmanInstrument::loadPatch(
psample->setLoopEndFrame( loop_end );
}

m_patchSamples.push_back( psample );
m_patchSamples.push_back( std::move(psample) );

delete[] wave_samples;
}
Expand All @@ -379,11 +379,7 @@ patmanInstrument::LoadErrors patmanInstrument::loadPatch(

void patmanInstrument::unloadCurrentPatch( void )
{
while( !m_patchSamples.empty() )
{
sharedObject::unref( m_patchSamples.back() );
m_patchSamples.pop_back();
}
m_patchFile.clear ();
}


Expand All @@ -394,30 +390,30 @@ void patmanInstrument::selectSample( NotePlayHandle * _n )
const float freq = _n->frequency();

float min_dist = HUGE_VALF;
SampleBuffer* sample = NULL;
std::shared_ptr<SampleBuffer> sample;

for( QVector<SampleBuffer *>::iterator it = m_patchSamples.begin(); it != m_patchSamples.end(); ++it )
for( auto &element : m_patchSamples )
{
float patch_freq = ( *it )->frequency();
float patch_freq = element->frequency();
float dist = freq >= patch_freq ? freq / patch_freq :
patch_freq / freq;

if( dist < min_dist )
{
min_dist = dist;
sample = *it;
sample = element;
}
}

handle_data * hdata = new handle_data;
hdata->tuned = m_tunedModel.value();
if( sample )
{
hdata->sample = sharedObject::ref( sample );
hdata->sample = sample;
}
else
{
hdata->sample = new SampleBuffer( NULL, 0 );
hdata->sample = std::make_shared<SampleBuffer>();
}
hdata->state = new SampleBuffer::handleState( _n->hasDetuningInfo() );

Expand Down
5 changes: 3 additions & 2 deletions plugins/patman/patman.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "SampleBuffer.h"
#include "AutomatableModel.h"
#include "MemoryManager.h"
#include <memory>

class PixmapButton;

Expand Down Expand Up @@ -82,11 +83,11 @@ public slots:
MM_OPERATORS
SampleBuffer::handleState* state;
bool tuned;
SampleBuffer* sample;
std::shared_ptr<SampleBuffer> sample;
} handle_data;

QString m_patchFile;
QVector<SampleBuffer *> m_patchSamples;
QVector<std::shared_ptr<SampleBuffer>> m_patchSamples;
BoolModel m_loopedModel;
BoolModel m_tunedModel;

Expand Down
2 changes: 1 addition & 1 deletion plugins/triple_oscillator/TripleOscillator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ OscillatorObject::OscillatorObject( Model * _parent, int _idx ) :

OscillatorObject::~OscillatorObject()
{
sharedObject::unref( m_sampleBuffer );
delete m_sampleBuffer;
}


Expand Down
2 changes: 1 addition & 1 deletion src/core/LfoController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ LfoController::LfoController( Model * _parent ) :

LfoController::~LfoController()
{
sharedObject::unref( m_userDefSampleBuffer );
delete m_userDefSampleBuffer;
m_baseModel.disconnect( this );
m_speedModel.disconnect( this );
m_amountModel.disconnect( this );
Expand Down
44 changes: 35 additions & 9 deletions src/core/SampleBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <QFileInfo>
#include <QMessageBox>
#include <QPainter>
#include <QDomElement>


#include <sndfile.h>
Expand Down Expand Up @@ -70,12 +71,12 @@ SampleBuffer::SampleBuffer() :


SampleBuffer::SampleBuffer( const QString & _audio_file,
bool _is_base64_data )
bool _is_base64_data, sample_rate_t sampleRate )
: SampleBuffer()
{
if( _is_base64_data )
{
loadFromBase64( _audio_file, false );
loadFromBase64( _audio_file, false, sampleRate );
}
else
{
Expand All @@ -97,7 +98,36 @@ SampleBuffer::SampleBuffer(SampleBuffer::DataVector &&movedData , sample_rate_t
);
}

void SampleBuffer::saveSettings(QDomDocument &doc, QDomElement &_this) {
{
QString string;
_this.setAttribute( "data", toBase64(string) );
}

_this.setAttribute ("sampleRate", sampleRate ());
_this.setAttribute ("amplification", amplification ());
_this.setAttribute ("frequency", frequency ());
}

void SampleBuffer::loadSettings(const QDomElement &_this) {
if (_this.hasAttribute ("sampleRate")) {
m_sampleRate = _this.attribute ("sampleRate").toUInt ();
} else {
qWarning("SampleBuffer::loadSettings: Using default sampleRate. That could lead to invalid values");
}

if (_this.hasAttribute ("amplification")) {
m_amplification = _this.attribute ("amplification").toFloat ();
}

if (_this.hasAttribute ("frequency")) {
m_frequency = _this.attribute ("frequency").toFloat ();
}

if (_this.hasAttribute ("data")) {
loadFromBase64 (_this.attribute("data"), m_sampleRate, true);
}
}

void SampleBuffer::sampleRateChanged() {
auto previousSampleRate = sampleRate ();
Expand Down Expand Up @@ -983,7 +1013,8 @@ void SampleBuffer::setAudioFile( const QString & _audio_file )



void SampleBuffer::loadFromBase64( const QString & _data , bool shouldLock)
void SampleBuffer::loadFromBase64( const QString & _data , sample_rate_t sampleRate,
bool shouldLock)
{
char * dst = NULL;
int dsize = 0;
Expand All @@ -1001,7 +1032,7 @@ void SampleBuffer::loadFromBase64( const QString & _data , bool shouldLock)
m_audioFile = QString();
doneBufferChange (shouldLock,
true,
sampleRate ());
sampleRate);
}


Expand Down Expand Up @@ -1030,11 +1061,6 @@ void SampleBuffer::setAmplification( float _a )
emit sampleUpdated();
}

//void SampleBuffer::setReversed(bool reversed)
//{
// m_reversed = reversed;
//}

QString SampleBuffer::tryToMakeRelative( const QString & file )
{
if( QFileInfo( file ).isRelative() == false )
Expand Down
Loading

0 comments on commit 84a1f35

Please sign in to comment.