Merge branch 'master' into sample-recording
This commit is contained in:
@@ -37,6 +37,7 @@ namespace lmms
|
||||
|
||||
class AudioEngine;
|
||||
class AudioPort;
|
||||
class SampleFrame;
|
||||
|
||||
|
||||
class AudioDevice
|
||||
@@ -92,14 +93,14 @@ public:
|
||||
protected:
|
||||
// subclasses can re-implement this for being used in conjunction with
|
||||
// processNextBuffer()
|
||||
virtual void writeBuffer(const surroundSampleFrame* /* _buf*/, const fpp_t /*_frames*/) {}
|
||||
virtual void writeBuffer(const SampleFrame* /* _buf*/, const fpp_t /*_frames*/) {}
|
||||
|
||||
// called by according driver for fetching new sound-data
|
||||
fpp_t getNextBuffer( surroundSampleFrame * _ab );
|
||||
fpp_t getNextBuffer(SampleFrame* _ab);
|
||||
|
||||
// convert a given audio-buffer to a buffer in signed 16-bit samples
|
||||
// returns num of bytes in outbuf
|
||||
int convertToS16( const surroundSampleFrame * _ab,
|
||||
int convertToS16(const SampleFrame* _ab,
|
||||
const fpp_t _frames,
|
||||
int_sample_t * _output_buffer,
|
||||
const bool _convert_endian = false );
|
||||
@@ -133,7 +134,7 @@ private:
|
||||
|
||||
QMutex m_devMutex;
|
||||
|
||||
surroundSampleFrame * m_buffer;
|
||||
SampleFrame* m_buffer;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ private:
|
||||
while( true )
|
||||
{
|
||||
timer.reset();
|
||||
const surroundSampleFrame* b = audioEngine()->nextBuffer();
|
||||
const SampleFrame* b = audioEngine()->nextBuffer();
|
||||
if( !b )
|
||||
{
|
||||
break;
|
||||
|
||||
@@ -25,18 +25,16 @@
|
||||
#ifndef LMMS_AUDIO_ENGINE_H
|
||||
#define LMMS_AUDIO_ENGINE_H
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#include <mingw.mutex.h>
|
||||
#else
|
||||
#include <mutex>
|
||||
#endif
|
||||
|
||||
#include <QThread>
|
||||
#include <samplerate.h>
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "lmms_basics.h"
|
||||
#include "SampleFrame.h"
|
||||
#include "LocklessList.h"
|
||||
#include "FifoBuffer.h"
|
||||
#include "AudioEngineProfiler.h"
|
||||
@@ -57,8 +55,7 @@ const fpp_t DEFAULT_BUFFER_SIZE = 256;
|
||||
|
||||
const int BYTES_PER_SAMPLE = sizeof( sample_t );
|
||||
const int BYTES_PER_INT_SAMPLE = sizeof( int_sample_t );
|
||||
const int BYTES_PER_FRAME = sizeof( sampleFrame );
|
||||
const int BYTES_PER_SURROUND_FRAME = sizeof( surroundSampleFrame );
|
||||
const int BYTES_PER_FRAME = sizeof( SampleFrame );
|
||||
|
||||
const float OUTPUT_SAMPLE_MULTIPLIER = 32767.0f;
|
||||
|
||||
@@ -268,15 +265,6 @@ public:
|
||||
}
|
||||
|
||||
|
||||
struct StereoSample
|
||||
{
|
||||
StereoSample(sample_t _left, sample_t _right) : left(_left), right(_right) {}
|
||||
sample_t left;
|
||||
sample_t right;
|
||||
};
|
||||
StereoSample getPeakValues(sampleFrame * ab, const f_cnt_t _frames) const;
|
||||
|
||||
|
||||
bool criticalXRuns() const;
|
||||
|
||||
inline bool hasFifoWriter() const
|
||||
@@ -284,9 +272,9 @@ public:
|
||||
return m_fifoWriter != nullptr;
|
||||
}
|
||||
|
||||
void pushInputFrames( sampleFrame * _ab, const f_cnt_t _frames );
|
||||
void pushInputFrames( SampleFrame* _ab, const f_cnt_t _frames );
|
||||
|
||||
inline const sampleFrame * inputBuffer()
|
||||
inline const SampleFrame* inputBuffer()
|
||||
{
|
||||
return m_inputBuffer[ m_inputBufferRead ];
|
||||
}
|
||||
@@ -296,7 +284,7 @@ public:
|
||||
return m_inputBufferFrames[ m_inputBufferRead ];
|
||||
}
|
||||
|
||||
inline const surroundSampleFrame * nextBuffer()
|
||||
inline const SampleFrame* nextBuffer()
|
||||
{
|
||||
return hasFifoWriter() ? m_fifo->read() : renderNextBuffer();
|
||||
}
|
||||
@@ -322,11 +310,11 @@ public:
|
||||
signals:
|
||||
void qualitySettingsChanged();
|
||||
void sampleRateChanged();
|
||||
void nextAudioBuffer( const lmms::surroundSampleFrame * buffer );
|
||||
void nextAudioBuffer(const lmms::SampleFrame* buffer);
|
||||
|
||||
|
||||
private:
|
||||
using Fifo = FifoBuffer<surroundSampleFrame*>;
|
||||
using Fifo = FifoBuffer<SampleFrame*>;
|
||||
|
||||
class fifoWriter : public QThread
|
||||
{
|
||||
@@ -343,7 +331,7 @@ private:
|
||||
|
||||
void run() override;
|
||||
|
||||
void write( surroundSampleFrame * buffer );
|
||||
void write(SampleFrame* buffer);
|
||||
} ;
|
||||
|
||||
|
||||
@@ -367,7 +355,7 @@ private:
|
||||
void renderStageEffects();
|
||||
void renderStageMix();
|
||||
|
||||
const surroundSampleFrame * renderNextBuffer();
|
||||
const SampleFrame* renderNextBuffer();
|
||||
|
||||
void swapBuffers();
|
||||
|
||||
@@ -381,14 +369,14 @@ private:
|
||||
|
||||
fpp_t m_framesPerPeriod;
|
||||
|
||||
sampleFrame * m_inputBuffer[2];
|
||||
SampleFrame* m_inputBuffer[2];
|
||||
f_cnt_t m_inputBufferFrames[2];
|
||||
f_cnt_t m_inputBufferSize[2];
|
||||
int m_inputBufferRead;
|
||||
int m_inputBufferWrite;
|
||||
|
||||
surroundSampleFrame * m_outputBufferRead;
|
||||
surroundSampleFrame * m_outputBufferWrite;
|
||||
std::unique_ptr<SampleFrame[]> m_outputBufferRead;
|
||||
std::unique_ptr<SampleFrame[]> m_outputBufferWrite;
|
||||
|
||||
// worker thread stuff
|
||||
std::vector<AudioEngineWorkerThread *> m_workers;
|
||||
@@ -425,7 +413,7 @@ private:
|
||||
|
||||
bool m_clearSignal;
|
||||
|
||||
std::mutex m_changeMutex;
|
||||
std::recursive_mutex m_changeMutex;
|
||||
|
||||
friend class Engine;
|
||||
friend class AudioEngineWorkerThread;
|
||||
|
||||
@@ -65,7 +65,7 @@ private:
|
||||
SF_INFO m_sfinfo;
|
||||
SNDFILE* m_sf;
|
||||
|
||||
void writeBuffer(surroundSampleFrame const* _ab, fpp_t const frames) override;
|
||||
void writeBuffer(const SampleFrame* _ab, fpp_t const frames) override;
|
||||
|
||||
bool startEncoding();
|
||||
void finishEncoding();
|
||||
|
||||
@@ -58,7 +58,7 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
void writeBuffer(const surroundSampleFrame* /* _buf*/, const fpp_t /*_frames*/) override;
|
||||
void writeBuffer(const SampleFrame* /* _buf*/, const fpp_t /*_frames*/) override;
|
||||
|
||||
private:
|
||||
void flushRemainingBuffers();
|
||||
|
||||
@@ -58,7 +58,7 @@ public:
|
||||
|
||||
|
||||
private:
|
||||
void writeBuffer(const surroundSampleFrame* _ab, const fpp_t _frames) override;
|
||||
void writeBuffer(const SampleFrame* _ab, const fpp_t _frames) override;
|
||||
|
||||
bool startEncoding();
|
||||
void finishEncoding();
|
||||
|
||||
@@ -56,7 +56,7 @@ public:
|
||||
|
||||
|
||||
private:
|
||||
void writeBuffer(const surroundSampleFrame* _ab, const fpp_t _frames) override;
|
||||
void writeBuffer(const SampleFrame* _ab, const fpp_t _frames) override;
|
||||
|
||||
bool startEncoding();
|
||||
void finishEncoding();
|
||||
|
||||
@@ -111,7 +111,7 @@ private:
|
||||
std::atomic<MidiJack*> m_midiClient;
|
||||
std::vector<jack_port_t*> m_outputPorts;
|
||||
jack_default_audio_sample_t** m_tempOutBufs;
|
||||
surroundSampleFrame* m_outBuf;
|
||||
SampleFrame* m_outBuf;
|
||||
|
||||
f_cnt_t m_framesDoneInCurBuf;
|
||||
f_cnt_t m_framesToDoInCurBuf;
|
||||
|
||||
@@ -46,7 +46,7 @@ public:
|
||||
BoolModel * mutedModel = nullptr );
|
||||
virtual ~AudioPort();
|
||||
|
||||
inline sampleFrame * buffer()
|
||||
inline SampleFrame* buffer()
|
||||
{
|
||||
return m_portBuffer;
|
||||
}
|
||||
@@ -112,7 +112,7 @@ public:
|
||||
private:
|
||||
volatile bool m_bufferUsage;
|
||||
|
||||
sampleFrame * m_portBuffer;
|
||||
SampleFrame* m_portBuffer;
|
||||
QMutex m_portBufferLock;
|
||||
|
||||
bool m_extOutputEnabled;
|
||||
|
||||
@@ -150,7 +150,7 @@ private:
|
||||
|
||||
bool m_wasPAInitError;
|
||||
|
||||
surroundSampleFrame * m_outBuf;
|
||||
SampleFrame* m_outBuf;
|
||||
int m_outBufPos;
|
||||
int m_outBufSize;
|
||||
|
||||
|
||||
@@ -48,9 +48,9 @@ public:
|
||||
std::shared_ptr<const SampleBuffer> createSampleBuffer();
|
||||
|
||||
private:
|
||||
void writeBuffer(const surroundSampleFrame* _ab, const fpp_t _frames) override;
|
||||
void writeBuffer(const SampleFrame* _ab, const fpp_t _frames) override;
|
||||
|
||||
using BufferList = QList<QPair<sampleFrame*, fpp_t>>;
|
||||
using BufferList = QList<QPair<SampleFrame*, fpp_t>>;
|
||||
BufferList m_buffers;
|
||||
|
||||
} ;
|
||||
|
||||
@@ -87,7 +87,7 @@ private:
|
||||
|
||||
SDL_AudioSpec m_audioHandle;
|
||||
|
||||
surroundSampleFrame * m_outBuf;
|
||||
SampleFrame* m_outBuf;
|
||||
|
||||
#ifdef LMMS_HAVE_SDL2
|
||||
size_t m_currentBufferFramePos;
|
||||
|
||||
@@ -110,7 +110,7 @@ private:
|
||||
SoundIo *m_soundio;
|
||||
SoundIoOutStream *m_outstream;
|
||||
|
||||
surroundSampleFrame * m_outBuf;
|
||||
SampleFrame* m_outBuf;
|
||||
int m_outBufSize;
|
||||
fpp_t m_outBufFramesTotal;
|
||||
fpp_t m_outBufFrameIndex;
|
||||
|
||||
@@ -32,20 +32,18 @@
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class SampleFrame;
|
||||
|
||||
class LMMS_EXPORT BufferManager
|
||||
{
|
||||
public:
|
||||
static void init( fpp_t fpp );
|
||||
static sampleFrame * acquire();
|
||||
static SampleFrame* acquire();
|
||||
// audio-buffer-mgm
|
||||
static void clear( sampleFrame * ab, const f_cnt_t frames,
|
||||
static void clear( SampleFrame* ab, const f_cnt_t frames,
|
||||
const f_cnt_t offset = 0 );
|
||||
#ifndef LMMS_DISABLE_SURROUND
|
||||
static void clear( surroundSampleFrame * ab, const f_cnt_t frames,
|
||||
const f_cnt_t offset = 0 );
|
||||
#endif
|
||||
static void release( sampleFrame * buf );
|
||||
|
||||
static void release( SampleFrame* buf );
|
||||
|
||||
private:
|
||||
static fpp_t s_framesPerPeriod;
|
||||
|
||||
@@ -27,33 +27,33 @@
|
||||
#define LMMS_DRUM_SYNTH_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "lmms_basics.h"
|
||||
|
||||
class QString;
|
||||
|
||||
namespace lmms
|
||||
namespace lmms {
|
||||
|
||||
class DrumSynth
|
||||
{
|
||||
public:
|
||||
DrumSynth() = default;
|
||||
int GetDSFileSamples(QString dsfile, int16_t*& wave, int channels, sample_rate_t Fs);
|
||||
|
||||
class DrumSynth {
|
||||
public:
|
||||
DrumSynth() = default;
|
||||
int GetDSFileSamples(QString dsfile, int16_t *&wave, int channels, sample_rate_t Fs);
|
||||
private:
|
||||
float LoudestEnv();
|
||||
int LongestEnv();
|
||||
void UpdateEnv(int e, long t);
|
||||
void GetEnv(int env, const char* sec, const char* key, QString ini);
|
||||
|
||||
private:
|
||||
float LoudestEnv();
|
||||
int LongestEnv();
|
||||
void UpdateEnv(int e, long t);
|
||||
void GetEnv(int env, const char *sec, const char *key, QString ini);
|
||||
|
||||
float waveform(float ph, int form);
|
||||
|
||||
int GetPrivateProfileString(const char *sec, const char *key, const char *def, char *buffer, int size, QString file);
|
||||
int GetPrivateProfileInt(const char *sec, const char *key, int def, QString file);
|
||||
float GetPrivateProfileFloat(const char *sec, const char *key, float def, QString file);
|
||||
float waveform(float ph, int form);
|
||||
|
||||
int GetPrivateProfileString(
|
||||
const char* sec, const char* key, const char* def, char* buffer, int size, QString file);
|
||||
int GetPrivateProfileInt(const char* sec, const char* key, int def, QString file);
|
||||
float GetPrivateProfileFloat(const char* sec, const char* key, float def, QString file);
|
||||
};
|
||||
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif // LMMS_DRUM_SYNTH_H
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#include "lmms_math.h"
|
||||
#include "lmms_constants.h"
|
||||
#include "lmms_basics.h"
|
||||
|
||||
#include "SampleFrame.h"
|
||||
|
||||
namespace lmms::DspEffectLibrary
|
||||
{
|
||||
@@ -80,6 +80,17 @@ namespace lmms::DspEffectLibrary
|
||||
{
|
||||
}
|
||||
|
||||
void setGain(float gain)
|
||||
{
|
||||
leftFX().setGain(gain);
|
||||
rightFX().setGain(gain);
|
||||
}
|
||||
|
||||
void nextSample(SampleFrame & in)
|
||||
{
|
||||
nextSample(in.left(), in.right());
|
||||
}
|
||||
|
||||
void nextSample( sample_t& inLeft, sample_t& inRight )
|
||||
{
|
||||
inLeft = m_leftFX.nextSample( inLeft );
|
||||
|
||||
@@ -107,7 +107,7 @@ public:
|
||||
return &m_controls;
|
||||
}
|
||||
|
||||
bool processAudioBuffer( sampleFrame *, const fpp_t ) override
|
||||
bool processAudioBuffer( SampleFrame*, const fpp_t ) override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -49,10 +49,9 @@ public:
|
||||
|
||||
~DummyInstrument() override = default;
|
||||
|
||||
void playNote( NotePlayHandle *, sampleFrame * buffer ) override
|
||||
void playNote( NotePlayHandle*, SampleFrame* buffer ) override
|
||||
{
|
||||
memset( buffer, 0, sizeof( sampleFrame ) *
|
||||
Engine::audioEngine()->framesPerPeriod() );
|
||||
zeroSampleFrames(buffer, Engine::audioEngine()->framesPerPeriod());
|
||||
}
|
||||
|
||||
void saveSettings( QDomDocument &, QDomElement & ) override
|
||||
|
||||
@@ -64,7 +64,7 @@ public:
|
||||
}
|
||||
|
||||
|
||||
virtual bool processAudioBuffer( sampleFrame * _buf,
|
||||
virtual bool processAudioBuffer( SampleFrame* _buf,
|
||||
const fpp_t _frames ) = 0;
|
||||
|
||||
inline ch_cnt_t processorCount() const
|
||||
@@ -187,8 +187,8 @@ protected:
|
||||
|
||||
// some effects might not be capable of higher sample-rates so they can
|
||||
// sample it down before processing and back after processing
|
||||
inline void sampleDown( const sampleFrame * _src_buf,
|
||||
sampleFrame * _dst_buf,
|
||||
inline void sampleDown( const SampleFrame* _src_buf,
|
||||
SampleFrame* _dst_buf,
|
||||
sample_rate_t _dst_sr )
|
||||
{
|
||||
resample( 0, _src_buf,
|
||||
@@ -197,8 +197,8 @@ protected:
|
||||
Engine::audioEngine()->framesPerPeriod() );
|
||||
}
|
||||
|
||||
inline void sampleBack( const sampleFrame * _src_buf,
|
||||
sampleFrame * _dst_buf,
|
||||
inline void sampleBack( const SampleFrame* _src_buf,
|
||||
SampleFrame* _dst_buf,
|
||||
sample_rate_t _src_sr )
|
||||
{
|
||||
resample( 1, _src_buf, _src_sr, _dst_buf,
|
||||
@@ -213,9 +213,9 @@ protected:
|
||||
|
||||
private:
|
||||
EffectChain * m_parent;
|
||||
void resample( int _i, const sampleFrame * _src_buf,
|
||||
void resample( int _i, const SampleFrame* _src_buf,
|
||||
sample_rate_t _src_sr,
|
||||
sampleFrame * _dst_buf, sample_rate_t _dst_sr,
|
||||
SampleFrame* _dst_buf, sample_rate_t _dst_sr,
|
||||
const f_cnt_t _frames );
|
||||
|
||||
ch_cnt_t m_processors;
|
||||
|
||||
@@ -34,6 +34,7 @@ namespace lmms
|
||||
{
|
||||
|
||||
class Effect;
|
||||
class SampleFrame;
|
||||
|
||||
namespace gui
|
||||
{
|
||||
@@ -62,7 +63,7 @@ public:
|
||||
void removeEffect( Effect * _effect );
|
||||
void moveDown( Effect * _effect );
|
||||
void moveUp( Effect * _effect );
|
||||
bool processAudioBuffer( sampleFrame * _buf, const fpp_t _frames, bool hasInputNoise );
|
||||
bool processAudioBuffer( SampleFrame* _buf, const fpp_t _frames, bool hasInputNoise );
|
||||
void startRunning();
|
||||
|
||||
void clear();
|
||||
|
||||
@@ -90,7 +90,7 @@ public:
|
||||
};
|
||||
return s_excludedPaths;
|
||||
}
|
||||
static QDir::Filters dirFilters() { return QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot; }
|
||||
static QDir::Filters dirFilters() { return QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot | QDir::Hidden; }
|
||||
static QDir::SortFlags sortFlags() { return QDir::LocaleAware | QDir::DirsFirst | QDir::Name | QDir::IgnoreCase; }
|
||||
|
||||
private slots:
|
||||
@@ -111,6 +111,8 @@ private:
|
||||
void onSearch(const QString& filter);
|
||||
void displaySearch(bool on);
|
||||
|
||||
void addContentCheckBox();
|
||||
|
||||
FileBrowserTreeWidget * m_fileBrowserTreeWidget;
|
||||
FileBrowserTreeWidget * m_searchTreeWidget;
|
||||
|
||||
@@ -124,9 +126,13 @@ private:
|
||||
|
||||
bool m_dirsAsItems;
|
||||
|
||||
void addContentCheckBox();
|
||||
QCheckBox* m_showUserContent = nullptr;
|
||||
QCheckBox* m_showFactoryContent = nullptr;
|
||||
QCheckBox* m_showHiddenContent = nullptr;
|
||||
|
||||
QBoxLayout *filterWidgetLayout = nullptr;
|
||||
QBoxLayout *hiddenWidgetLayout = nullptr;
|
||||
QBoxLayout *outerLayout = nullptr;
|
||||
QString m_userDir;
|
||||
QString m_factoryDir;
|
||||
QList<QString> m_savedExpandedDirs;
|
||||
|
||||
@@ -45,6 +45,7 @@ class InstrumentTrack;
|
||||
class MidiEvent;
|
||||
class NotePlayHandle;
|
||||
class Track;
|
||||
class SampleFrame;
|
||||
|
||||
|
||||
class LMMS_EXPORT Instrument : public Plugin
|
||||
@@ -75,11 +76,11 @@ public:
|
||||
// if the plugin doesn't play each note, it can create an instrument-
|
||||
// play-handle and re-implement this method, so that it mixes its
|
||||
// output buffer only once per audio engine period
|
||||
virtual void play( sampleFrame * _working_buffer );
|
||||
virtual void play( SampleFrame* _working_buffer );
|
||||
|
||||
// to be implemented by actual plugin
|
||||
virtual void playNote( NotePlayHandle * /* _note_to_play */,
|
||||
sampleFrame * /* _working_buf */ )
|
||||
SampleFrame* /* _working_buf */ )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -160,12 +161,12 @@ public:
|
||||
|
||||
protected:
|
||||
// fade in to prevent clicks
|
||||
void applyFadeIn(sampleFrame * buf, NotePlayHandle * n);
|
||||
void applyFadeIn(SampleFrame* buf, NotePlayHandle * n);
|
||||
|
||||
// instruments may use this to apply a soft fade out at the end of
|
||||
// notes - method does this only if really less or equal
|
||||
// desiredReleaseFrames() frames are left
|
||||
void applyRelease( sampleFrame * buf, const NotePlayHandle * _n );
|
||||
void applyRelease( SampleFrame* buf, const NotePlayHandle * _n );
|
||||
|
||||
float computeReleaseTimeMsByFrameCount(f_cnt_t frames) const;
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ public:
|
||||
|
||||
~InstrumentPlayHandle() override = default;
|
||||
|
||||
void play(sampleFrame * working_buffer) override;
|
||||
void play(SampleFrame* working_buffer) override;
|
||||
|
||||
bool isFinished() const override
|
||||
{
|
||||
|
||||
@@ -34,6 +34,7 @@ namespace lmms
|
||||
class InstrumentTrack;
|
||||
class EnvelopeAndLfoParameters;
|
||||
class NotePlayHandle;
|
||||
class SampleFrame;
|
||||
|
||||
namespace gui
|
||||
{
|
||||
@@ -48,7 +49,7 @@ public:
|
||||
InstrumentSoundShaping( InstrumentTrack * _instrument_track );
|
||||
~InstrumentSoundShaping() override = default;
|
||||
|
||||
void processAudioBuffer( sampleFrame * _ab, const fpp_t _frames,
|
||||
void processAudioBuffer( SampleFrame* _ab, const fpp_t _frames,
|
||||
NotePlayHandle * _n );
|
||||
|
||||
enum class Target
|
||||
|
||||
@@ -66,7 +66,7 @@ public:
|
||||
~InstrumentTrack() override;
|
||||
|
||||
// used by instrument
|
||||
void processAudioBuffer( sampleFrame * _buf, const fpp_t _frames,
|
||||
void processAudioBuffer( SampleFrame* _buf, const fpp_t _frames,
|
||||
NotePlayHandle * _n );
|
||||
|
||||
MidiEvent applyMasterKey( const MidiEvent& event );
|
||||
@@ -86,7 +86,7 @@ public:
|
||||
|
||||
// for capturing note-play-events -> need that for arpeggio,
|
||||
// filter and so on
|
||||
void playNote( NotePlayHandle * _n, sampleFrame * _working_buffer );
|
||||
void playNote( NotePlayHandle * _n, SampleFrame* _working_buffer );
|
||||
|
||||
QString instrumentName() const;
|
||||
const Instrument *instrument() const
|
||||
|
||||
@@ -43,6 +43,7 @@ namespace lmms
|
||||
|
||||
class Lv2Proc;
|
||||
class PluginIssue;
|
||||
class SampleFrame;
|
||||
|
||||
/**
|
||||
Common base class for Lv2 plugins
|
||||
@@ -118,9 +119,9 @@ protected:
|
||||
void copyModelsToLmms() const;
|
||||
|
||||
//! Copy buffer passed by LMMS into our ports
|
||||
void copyBuffersFromLmms(const sampleFrame *buf, fpp_t frames);
|
||||
void copyBuffersFromLmms(const SampleFrame* buf, fpp_t frames);
|
||||
//! Copy our ports into buffers passed by LMMS
|
||||
void copyBuffersToLmms(sampleFrame *buf, fpp_t frames) const;
|
||||
void copyBuffersToLmms(SampleFrame* buf, fpp_t frames) const;
|
||||
//! Run the Lv2 plugin instance for @param frames frames
|
||||
void run(fpp_t frames);
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class SampleFrame;
|
||||
|
||||
struct ConnectPortVisitor;
|
||||
using LV2_Evbuf = struct LV2_Evbuf_Impl;
|
||||
@@ -184,15 +185,15 @@ struct Audio : public VisitablePort<Audio, PortBase>
|
||||
|
||||
//! Copy buffer passed by LMMS into our ports
|
||||
//! @param channel channel index into each sample frame
|
||||
void copyBuffersFromCore(const sampleFrame *lmmsBuf,
|
||||
void copyBuffersFromCore(const SampleFrame* lmmsBuf,
|
||||
unsigned channel, fpp_t frames);
|
||||
//! Add buffer passed by LMMS into our ports, and halve the result
|
||||
//! @param channel channel index into each sample frame
|
||||
void averageWithBuffersFromCore(const sampleFrame *lmmsBuf,
|
||||
void averageWithBuffersFromCore(const SampleFrame* lmmsBuf,
|
||||
unsigned channel, fpp_t frames);
|
||||
//! Copy our ports into buffers passed by LMMS
|
||||
//! @param channel channel index into each sample frame
|
||||
void copyBuffersToCore(sampleFrame *lmmsBuf,
|
||||
void copyBuffersToCore(SampleFrame* lmmsBuf,
|
||||
unsigned channel, fpp_t frames) const;
|
||||
|
||||
bool isSideChain() const { return m_sidechain; }
|
||||
|
||||
@@ -49,6 +49,7 @@ namespace lmms
|
||||
{
|
||||
|
||||
class PluginIssue;
|
||||
class SampleFrame;
|
||||
|
||||
// forward declare port structs/enums
|
||||
namespace Lv2Ports
|
||||
@@ -134,7 +135,7 @@ public:
|
||||
* @param num Number of channels we must read from @param buf (starting at
|
||||
* @p offset)
|
||||
*/
|
||||
void copyBuffersFromCore(const sampleFrame *buf,
|
||||
void copyBuffersFromCore(const SampleFrame* buf,
|
||||
unsigned firstChan, unsigned num, fpp_t frames);
|
||||
/**
|
||||
* Copy our ports into buffers passed by the core
|
||||
@@ -147,7 +148,7 @@ public:
|
||||
* @param num Number of channels we must write to @param buf (starting at
|
||||
* @p offset)
|
||||
*/
|
||||
void copyBuffersToCore(sampleFrame *buf, unsigned firstChan, unsigned num,
|
||||
void copyBuffersToCore(SampleFrame* buf, unsigned firstChan, unsigned num,
|
||||
fpp_t frames) const;
|
||||
//! Run the Lv2 plugin instance for @param frames frames
|
||||
void run(fpp_t frames);
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Simon Symeonidis <lethaljellybean/at/gmail/com>
|
||||
* Copyright (c) 2004-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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LMMS_MEMORY_HELPER_H
|
||||
#define LMMS_MEMORY_HELPER_H
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* Helper class to alocate aligned memory and free it.
|
||||
*/
|
||||
class MemoryHelper {
|
||||
public:
|
||||
|
||||
static void* alignedMalloc( size_t );
|
||||
|
||||
static void alignedFree( void* );
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif // LMMS_MEMORY_HELPER_H
|
||||
@@ -31,52 +31,54 @@ namespace lmms
|
||||
{
|
||||
|
||||
class ValueBuffer;
|
||||
class SampleFrame;
|
||||
|
||||
namespace MixHelpers
|
||||
{
|
||||
|
||||
bool isSilent( const sampleFrame* src, int frames );
|
||||
bool isSilent( const SampleFrame* src, int frames );
|
||||
|
||||
bool useNaNHandler();
|
||||
|
||||
void setNaNHandler( bool use );
|
||||
|
||||
bool sanitize( sampleFrame * src, int frames );
|
||||
bool sanitize( SampleFrame* src, int frames );
|
||||
|
||||
/*! \brief Add samples from src to dst */
|
||||
void add( sampleFrame* dst, const sampleFrame* src, int frames );
|
||||
void add( SampleFrame* dst, const SampleFrame* src, int frames );
|
||||
|
||||
/*! \brief Multiply samples from `dst` by `coeff` */
|
||||
void multiply(sampleFrame* dst, float coeff, int frames);
|
||||
void multiply(SampleFrame* dst, float coeff, int frames);
|
||||
|
||||
/*! \brief Add samples from src multiplied by coeffSrc to dst */
|
||||
void addMultiplied( sampleFrame* dst, const sampleFrame* src, float coeffSrc, int frames );
|
||||
void addMultiplied( SampleFrame* dst, const SampleFrame* src, float coeffSrc, int frames );
|
||||
|
||||
/*! \brief Add samples from src multiplied by coeffSrc to dst, swap inputs */
|
||||
void addSwappedMultiplied( sampleFrame* dst, const sampleFrame* src, float coeffSrc, int frames );
|
||||
void addSwappedMultiplied( SampleFrame* dst, const SampleFrame* src, float coeffSrc, int frames );
|
||||
|
||||
/*! \brief Add samples from src multiplied by coeffSrc and coeffSrcBuf to dst */
|
||||
void addMultipliedByBuffer( sampleFrame* dst, const sampleFrame* src, float coeffSrc, ValueBuffer * coeffSrcBuf, int frames );
|
||||
void addMultipliedByBuffer( SampleFrame* dst, const SampleFrame* src, float coeffSrc, ValueBuffer * coeffSrcBuf, int frames );
|
||||
|
||||
/*! \brief Add samples from src multiplied by coeffSrc and coeffSrcBuf to dst */
|
||||
void addMultipliedByBuffers( sampleFrame* dst, const sampleFrame* src, ValueBuffer * coeffSrcBuf1, ValueBuffer * coeffSrcBuf2, int frames );
|
||||
void addMultipliedByBuffers( SampleFrame* dst, const SampleFrame* src, ValueBuffer * coeffSrcBuf1, ValueBuffer * coeffSrcBuf2, int frames );
|
||||
|
||||
/*! \brief Same as addMultiplied, but sanitize output (strip out infs/nans) */
|
||||
void addSanitizedMultiplied( sampleFrame* dst, const sampleFrame* src, float coeffSrc, int frames );
|
||||
void addSanitizedMultiplied( SampleFrame* dst, const SampleFrame* src, float coeffSrc, int frames );
|
||||
|
||||
/*! \brief Add samples from src multiplied by coeffSrc and coeffSrcBuf to dst - sanitized version */
|
||||
void addSanitizedMultipliedByBuffer( sampleFrame* dst, const sampleFrame* src, float coeffSrc, ValueBuffer * coeffSrcBuf, int frames );
|
||||
void addSanitizedMultipliedByBuffer( SampleFrame* dst, const SampleFrame* src, float coeffSrc, ValueBuffer * coeffSrcBuf, int frames );
|
||||
|
||||
/*! \brief Add samples from src multiplied by coeffSrc and coeffSrcBuf to dst - sanitized version */
|
||||
void addSanitizedMultipliedByBuffers( sampleFrame* dst, const sampleFrame* src, ValueBuffer * coeffSrcBuf1, ValueBuffer * coeffSrcBuf2, int frames );
|
||||
void addSanitizedMultipliedByBuffers( SampleFrame* dst, const SampleFrame* src, ValueBuffer * coeffSrcBuf1, ValueBuffer * coeffSrcBuf2, int frames );
|
||||
|
||||
/*! \brief Add samples from src multiplied by coeffSrcLeft/coeffSrcRight to dst */
|
||||
void addMultipliedStereo( sampleFrame* dst, const sampleFrame* src, float coeffSrcLeft, float coeffSrcRight, int frames );
|
||||
void addMultipliedStereo( SampleFrame* dst, const SampleFrame* src, float coeffSrcLeft, float coeffSrcRight, int frames );
|
||||
|
||||
/*! \brief Multiply dst by coeffDst and add samples from src multiplied by coeffSrc */
|
||||
void multiplyAndAddMultiplied( sampleFrame* dst, const sampleFrame* src, float coeffDst, float coeffSrc, int frames );
|
||||
void multiplyAndAddMultiplied( SampleFrame* dst, const SampleFrame* src, float coeffDst, float coeffSrc, int frames );
|
||||
|
||||
/*! \brief Multiply dst by coeffDst and add samples from srcLeft/srcRight multiplied by coeffSrc */
|
||||
void multiplyAndAddMultipliedJoined( sampleFrame* dst, const sample_t* srcLeft, const sample_t* srcRight, float coeffDst, float coeffSrc, int frames );
|
||||
void multiplyAndAddMultipliedJoined( SampleFrame* dst, const sample_t* srcLeft, const sample_t* srcRight, float coeffDst, float coeffSrc, int frames );
|
||||
|
||||
} // namespace MixHelpers
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ class MixerChannel : public ThreadableJob
|
||||
|
||||
float m_peakLeft;
|
||||
float m_peakRight;
|
||||
sampleFrame * m_buffer;
|
||||
SampleFrame* m_buffer;
|
||||
bool m_muteBeforeSolo;
|
||||
BoolModel m_muteModel;
|
||||
BoolModel m_soloModel;
|
||||
@@ -137,10 +137,10 @@ public:
|
||||
Mixer();
|
||||
~Mixer() override;
|
||||
|
||||
void mixToChannel( const sampleFrame * _buf, mix_ch_t _ch );
|
||||
void mixToChannel( const SampleFrame* _buf, mix_ch_t _ch );
|
||||
|
||||
void prepareMasterMix();
|
||||
void masterMix( sampleFrame * _buf );
|
||||
void masterMix( SampleFrame* _buf );
|
||||
|
||||
void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;
|
||||
void loadSettings( const QDomElement & _this ) override;
|
||||
|
||||
@@ -110,7 +110,7 @@ public:
|
||||
float currentDetuning() const { return m_baseDetuning->value(); }
|
||||
|
||||
/*! Renders one chunk using the attached instrument into the buffer */
|
||||
void play( sampleFrame* buffer ) override;
|
||||
void play( SampleFrame* buffer ) override;
|
||||
|
||||
/*! Returns whether playback of note is finished and thus handle can be deleted */
|
||||
bool isFinished() const override
|
||||
|
||||
@@ -109,7 +109,7 @@ public:
|
||||
m_userAntiAliasWaveTable = waveform;
|
||||
}
|
||||
|
||||
void update(sampleFrame* ab, const fpp_t frames, const ch_cnt_t chnl, bool modulator = false);
|
||||
void update(SampleFrame* ab, const fpp_t frames, const ch_cnt_t chnl, bool modulator = false);
|
||||
|
||||
// now follow the wave-shape-routines...
|
||||
static inline sample_t sinSample( const float _sample )
|
||||
@@ -282,40 +282,40 @@ private:
|
||||
/* End Multiband wavetable */
|
||||
|
||||
|
||||
void updateNoSub( sampleFrame * _ab, const fpp_t _frames,
|
||||
void updateNoSub( SampleFrame* _ab, const fpp_t _frames,
|
||||
const ch_cnt_t _chnl );
|
||||
void updatePM( sampleFrame * _ab, const fpp_t _frames,
|
||||
void updatePM( SampleFrame* _ab, const fpp_t _frames,
|
||||
const ch_cnt_t _chnl );
|
||||
void updateAM( sampleFrame * _ab, const fpp_t _frames,
|
||||
void updateAM( SampleFrame* _ab, const fpp_t _frames,
|
||||
const ch_cnt_t _chnl );
|
||||
void updateMix( sampleFrame * _ab, const fpp_t _frames,
|
||||
void updateMix( SampleFrame* _ab, const fpp_t _frames,
|
||||
const ch_cnt_t _chnl );
|
||||
void updateSync( sampleFrame * _ab, const fpp_t _frames,
|
||||
void updateSync( SampleFrame* _ab, const fpp_t _frames,
|
||||
const ch_cnt_t _chnl );
|
||||
void updateFM( sampleFrame * _ab, const fpp_t _frames,
|
||||
void updateFM( SampleFrame* _ab, const fpp_t _frames,
|
||||
const ch_cnt_t _chnl );
|
||||
|
||||
float syncInit( sampleFrame * _ab, const fpp_t _frames,
|
||||
float syncInit( SampleFrame* _ab, const fpp_t _frames,
|
||||
const ch_cnt_t _chnl );
|
||||
inline bool syncOk( float _osc_coeff );
|
||||
|
||||
template<WaveShape W>
|
||||
void updateNoSub( sampleFrame * _ab, const fpp_t _frames,
|
||||
void updateNoSub( SampleFrame* _ab, const fpp_t _frames,
|
||||
const ch_cnt_t _chnl );
|
||||
template<WaveShape W>
|
||||
void updatePM( sampleFrame * _ab, const fpp_t _frames,
|
||||
void updatePM( SampleFrame* _ab, const fpp_t _frames,
|
||||
const ch_cnt_t _chnl );
|
||||
template<WaveShape W>
|
||||
void updateAM( sampleFrame * _ab, const fpp_t _frames,
|
||||
void updateAM( SampleFrame* _ab, const fpp_t _frames,
|
||||
const ch_cnt_t _chnl );
|
||||
template<WaveShape W>
|
||||
void updateMix( sampleFrame * _ab, const fpp_t _frames,
|
||||
void updateMix( SampleFrame* _ab, const fpp_t _frames,
|
||||
const ch_cnt_t _chnl );
|
||||
template<WaveShape W>
|
||||
void updateSync( sampleFrame * _ab, const fpp_t _frames,
|
||||
void updateSync( SampleFrame* _ab, const fpp_t _frames,
|
||||
const ch_cnt_t _chnl );
|
||||
template<WaveShape W>
|
||||
void updateFM( sampleFrame * _ab, const fpp_t _frames,
|
||||
void updateFM( SampleFrame* _ab, const fpp_t _frames,
|
||||
const ch_cnt_t _chnl );
|
||||
|
||||
template<WaveShape W>
|
||||
|
||||
@@ -30,6 +30,13 @@
|
||||
|
||||
#include "lmms_basics.h"
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class SampleFrame;
|
||||
|
||||
}
|
||||
|
||||
namespace lmms::gui
|
||||
{
|
||||
|
||||
@@ -67,7 +74,7 @@ protected:
|
||||
|
||||
|
||||
protected slots:
|
||||
void updateAudioBuffer( const lmms::surroundSampleFrame * buffer );
|
||||
void updateAudioBuffer(const lmms::SampleFrame* buffer);
|
||||
|
||||
private:
|
||||
bool clips(float level) const;
|
||||
@@ -76,7 +83,7 @@ private:
|
||||
QPixmap m_background;
|
||||
QPointF * m_points;
|
||||
|
||||
sampleFrame * m_buffer;
|
||||
SampleFrame* m_buffer;
|
||||
bool m_active;
|
||||
|
||||
QColor m_leftChannelColor;
|
||||
|
||||
@@ -41,6 +41,7 @@ namespace lmms
|
||||
|
||||
class Track;
|
||||
class AudioPort;
|
||||
class SampleFrame;
|
||||
|
||||
class LMMS_EXPORT PlayHandle : public ThreadableJob
|
||||
{
|
||||
@@ -105,7 +106,7 @@ public:
|
||||
{
|
||||
return m_processingLock.tryLock();
|
||||
}
|
||||
virtual void play( sampleFrame* buffer ) = 0;
|
||||
virtual void play( SampleFrame* buffer ) = 0;
|
||||
virtual bool isFinished() const = 0;
|
||||
|
||||
// returns the frameoffset at the start of the playhandle,
|
||||
@@ -145,14 +146,14 @@ public:
|
||||
|
||||
void releaseBuffer();
|
||||
|
||||
sampleFrame * buffer();
|
||||
SampleFrame* buffer();
|
||||
|
||||
private:
|
||||
Type m_type;
|
||||
f_cnt_t m_offset;
|
||||
QThread* m_affinity;
|
||||
QMutex m_processingLock;
|
||||
sampleFrame* m_playHandleBuffer;
|
||||
SampleFrame* m_playHandleBuffer;
|
||||
bool m_bufferReleased;
|
||||
bool m_usesBuffer;
|
||||
AudioPort * m_audioPort;
|
||||
|
||||
@@ -47,7 +47,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
void play( sampleFrame* buffer ) override;
|
||||
void play( SampleFrame* buffer ) override;
|
||||
bool isFinished() const override;
|
||||
|
||||
bool isFromTrack( const Track * _track ) const override;
|
||||
|
||||
@@ -37,6 +37,7 @@ namespace lmms
|
||||
|
||||
|
||||
class RemotePlugin;
|
||||
class SampleFrame;
|
||||
|
||||
class ProcessWatcher : public QThread
|
||||
{
|
||||
@@ -96,7 +97,7 @@ public:
|
||||
|
||||
bool processMessage( const message & _m ) override;
|
||||
|
||||
bool process( const sampleFrame * _in_buf, sampleFrame * _out_buf );
|
||||
bool process( const SampleFrame* _in_buf, SampleFrame* _out_buf );
|
||||
|
||||
void processMidiEvent( const MidiEvent&, const f_cnt_t _offset );
|
||||
|
||||
|
||||
@@ -44,6 +44,8 @@
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class SampleFrame;
|
||||
|
||||
class RemotePluginClient : public RemotePluginBase
|
||||
{
|
||||
public:
|
||||
@@ -58,8 +60,8 @@ public:
|
||||
|
||||
bool processMessage( const message & _m ) override;
|
||||
|
||||
virtual void process( const sampleFrame * _in_buf,
|
||||
sampleFrame * _out_buf ) = 0;
|
||||
virtual void process( const SampleFrame* _in_buf,
|
||||
SampleFrame* _out_buf ) = 0;
|
||||
|
||||
virtual void processMidiEvent( const MidiEvent&, const f_cnt_t /* _offset */ )
|
||||
{
|
||||
@@ -342,8 +344,8 @@ void RemotePluginClient::doProcessing()
|
||||
{
|
||||
if (m_audioBuffer)
|
||||
{
|
||||
process( (sampleFrame *)( m_inputCount > 0 ? m_audioBuffer.get() : nullptr ),
|
||||
(sampleFrame *)( m_audioBuffer.get() +
|
||||
process( (SampleFrame*)( m_inputCount > 0 ? m_audioBuffer.get() : nullptr ),
|
||||
(SampleFrame*)( m_audioBuffer.get() +
|
||||
( m_inputCount*m_bufferSize ) ) );
|
||||
}
|
||||
else
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class SampleFrame;
|
||||
|
||||
/** \brief A basic LMMS ring buffer for single-thread use. For thread and realtime safe alternative see LocklessRingBuffer.
|
||||
*/
|
||||
@@ -105,7 +106,7 @@ public:
|
||||
* to a specified destination, and advances the position by one period
|
||||
* \param dst Destination pointer
|
||||
*/
|
||||
void pop( sampleFrame * dst );
|
||||
void pop( SampleFrame* dst );
|
||||
|
||||
// note: ringbuffer position is unaffected by all other read functions beside pop()
|
||||
|
||||
@@ -113,27 +114,27 @@ public:
|
||||
* \param dst Destination pointer
|
||||
* \param offset Offset in frames against current position, may be negative
|
||||
*/
|
||||
void read( sampleFrame * dst, f_cnt_t offset=0 );
|
||||
void read( SampleFrame* dst, f_cnt_t offset = 0 );
|
||||
|
||||
/** \brief Reads a period-sized buffer from the ringbuffer and writes it to a specified destination
|
||||
* \param dst Destination pointer
|
||||
* \param offset Offset in milliseconds against current position, may be negative
|
||||
*/
|
||||
void read( sampleFrame * dst, float offset );
|
||||
void read( SampleFrame* dst, float offset );
|
||||
|
||||
/** \brief Reads a buffer of specified size from the ringbuffer and writes it to a specified destination
|
||||
* \param dst Destination pointer
|
||||
* \param offset Offset in frames against current position, may be negative
|
||||
* \param length Length in frames of the buffer to read - must not be higher than the size of the ringbuffer!
|
||||
*/
|
||||
void read( sampleFrame * dst, f_cnt_t offset, f_cnt_t length );
|
||||
void read( SampleFrame* dst, f_cnt_t offset, f_cnt_t length );
|
||||
|
||||
/** \brief Reads a buffer of specified size from the ringbuffer and writes it to a specified destination
|
||||
* \param dst Destination pointer
|
||||
* \param offset Offset in milliseconds against current position, may be negative
|
||||
* \param length Length in frames of the buffer to read - must not be higher than the size of the ringbuffer!
|
||||
*/
|
||||
void read( sampleFrame * dst, float offset, f_cnt_t length );
|
||||
void read( SampleFrame* dst, float offset, f_cnt_t length );
|
||||
|
||||
|
||||
// write functions
|
||||
@@ -143,28 +144,28 @@ public:
|
||||
* \param offset Offset in frames against current position, may *NOT* be negative
|
||||
* \param length Length of the source buffer, if zero, period size is used - must not be higher than the size of the ringbuffer!
|
||||
*/
|
||||
void write( sampleFrame * src, f_cnt_t offset=0, f_cnt_t length=0 );
|
||||
void write( SampleFrame* src, f_cnt_t offset=0, f_cnt_t length=0 );
|
||||
|
||||
/** \brief Writes a buffer of sampleframes to the ringbuffer at specified position
|
||||
* \param src Pointer to the source buffer
|
||||
* \param offset Offset in milliseconds against current position, may *NOT* be negative
|
||||
* \param length Length of the source buffer, if zero, period size is used - must not be higher than the size of the ringbuffer!
|
||||
*/
|
||||
void write( sampleFrame * src, float offset, f_cnt_t length=0 );
|
||||
void write( SampleFrame* src, float offset, f_cnt_t length=0 );
|
||||
|
||||
/** \brief Mixes a buffer of sampleframes additively to the ringbuffer at specified position
|
||||
* \param src Pointer to the source buffer
|
||||
* \param offset Offset in frames against current position, may *NOT* be negative
|
||||
* \param length Length of the source buffer, if zero, period size is used - must not be higher than the size of the ringbuffer!
|
||||
*/
|
||||
void writeAdding( sampleFrame * src, f_cnt_t offset=0, f_cnt_t length=0 );
|
||||
void writeAdding( SampleFrame* src, f_cnt_t offset=0, f_cnt_t length=0 );
|
||||
|
||||
/** \brief Mixes a buffer of sampleframes additively to the ringbuffer at specified position
|
||||
* \param src Pointer to the source buffer
|
||||
* \param offset Offset in milliseconds against current position, may *NOT* be negative
|
||||
* \param length Length of the source buffer, if zero, period size is used - must not be higher than the size of the ringbuffer!
|
||||
*/
|
||||
void writeAdding( sampleFrame * src, float offset, f_cnt_t length=0 );
|
||||
void writeAdding( SampleFrame* src, float offset, f_cnt_t length=0 );
|
||||
|
||||
/** \brief Mixes a buffer of sampleframes additively to the ringbuffer at specified position, with
|
||||
* a specified multiplier applied to the frames
|
||||
@@ -173,7 +174,7 @@ public:
|
||||
* \param length Length of the source buffer, if zero, period size is used - must not be higher than the size of the ringbuffer!
|
||||
* \param level Multiplier applied to the frames before they're written to the ringbuffer
|
||||
*/
|
||||
void writeAddingMultiplied( sampleFrame * src, f_cnt_t offset, f_cnt_t length, float level );
|
||||
void writeAddingMultiplied( SampleFrame* src, f_cnt_t offset, f_cnt_t length, float level );
|
||||
|
||||
/** \brief Mixes a buffer of sampleframes additively to the ringbuffer at specified position, with
|
||||
* a specified multiplier applied to the frames
|
||||
@@ -182,7 +183,7 @@ public:
|
||||
* \param length Length of the source buffer, if zero, period size is used
|
||||
* \param level Multiplier applied to the frames before they're written to the ringbuffer
|
||||
*/
|
||||
void writeAddingMultiplied( sampleFrame * src, float offset, f_cnt_t length, float level );
|
||||
void writeAddingMultiplied( SampleFrame* src, float offset, f_cnt_t length, float level );
|
||||
|
||||
/** \brief Mixes a buffer of sampleframes additively to the ringbuffer at specified position, with
|
||||
* a specified multiplier applied to the frames, with swapped channels
|
||||
@@ -191,7 +192,7 @@ public:
|
||||
* \param length Length of the source buffer, if zero, period size is used - must not be higher than the size of the ringbuffer!
|
||||
* \param level Multiplier applied to the frames before they're written to the ringbuffer
|
||||
*/
|
||||
void writeSwappedAddingMultiplied( sampleFrame * src, f_cnt_t offset, f_cnt_t length, float level );
|
||||
void writeSwappedAddingMultiplied( SampleFrame* src, f_cnt_t offset, f_cnt_t length, float level );
|
||||
|
||||
/** \brief Mixes a buffer of sampleframes additively to the ringbuffer at specified position, with
|
||||
* a specified multiplier applied to the frames, with swapped channels
|
||||
@@ -200,7 +201,7 @@ public:
|
||||
* \param length Length of the source buffer, if zero, period size is used
|
||||
* \param level Multiplier applied to the frames before they're written to the ringbuffer
|
||||
*/
|
||||
void writeSwappedAddingMultiplied( sampleFrame * src, float offset, f_cnt_t length, float level );
|
||||
void writeSwappedAddingMultiplied( SampleFrame* src, float offset, f_cnt_t length, float level );
|
||||
|
||||
|
||||
protected slots:
|
||||
@@ -215,7 +216,7 @@ private:
|
||||
const fpp_t m_fpp;
|
||||
sample_rate_t m_samplerate;
|
||||
size_t m_size;
|
||||
sampleFrame * m_buffer;
|
||||
SampleFrame* m_buffer;
|
||||
volatile unsigned int m_position;
|
||||
|
||||
};
|
||||
|
||||
@@ -78,7 +78,7 @@ public:
|
||||
|
||||
Sample() = default;
|
||||
Sample(const QByteArray& base64, int sampleRate = Engine::audioEngine()->outputSampleRate());
|
||||
Sample(const sampleFrame* data, size_t numFrames, int sampleRate = Engine::audioEngine()->outputSampleRate());
|
||||
Sample(const SampleFrame* data, size_t numFrames, int sampleRate = Engine::audioEngine()->outputSampleRate());
|
||||
Sample(const Sample& other);
|
||||
Sample(Sample&& other);
|
||||
explicit Sample(const QString& audioFile);
|
||||
@@ -87,7 +87,7 @@ public:
|
||||
auto operator=(const Sample&) -> Sample&;
|
||||
auto operator=(Sample&&) -> Sample&;
|
||||
|
||||
auto play(sampleFrame* dst, PlaybackState* state, size_t numFrames, float desiredFrequency = DefaultBaseFreq,
|
||||
auto play(SampleFrame* dst, PlaybackState* state, size_t numFrames, float desiredFrequency = DefaultBaseFreq,
|
||||
Loop loopMode = Loop::Off) const -> bool;
|
||||
|
||||
auto sampleDuration() const -> std::chrono::milliseconds;
|
||||
@@ -97,7 +97,7 @@ public:
|
||||
|
||||
auto toBase64() const -> QString { return m_buffer->toBase64(); }
|
||||
|
||||
auto data() const -> const sampleFrame* { return m_buffer->data(); }
|
||||
auto data() const -> const SampleFrame* { return m_buffer->data(); }
|
||||
auto buffer() const -> std::shared_ptr<const SampleBuffer> { return m_buffer; }
|
||||
auto startFrame() const -> int { return m_startFrame.load(std::memory_order_relaxed); }
|
||||
auto endFrame() const -> int { return m_endFrame.load(std::memory_order_relaxed); }
|
||||
@@ -117,7 +117,7 @@ public:
|
||||
void setReversed(bool reversed) { m_reversed.store(reversed, std::memory_order_relaxed); }
|
||||
|
||||
private:
|
||||
void playRaw(sampleFrame* dst, size_t numFrames, const PlaybackState* state, Loop loopMode) const;
|
||||
void playRaw(SampleFrame* dst, size_t numFrames, const PlaybackState* state, Loop loopMode) const;
|
||||
void advance(PlaybackState* state, size_t advanceAmount, Loop loopMode) const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -41,22 +41,22 @@ namespace lmms {
|
||||
class LMMS_EXPORT SampleBuffer
|
||||
{
|
||||
public:
|
||||
using value_type = sampleFrame;
|
||||
using reference = sampleFrame&;
|
||||
using const_reference = const sampleFrame&;
|
||||
using iterator = std::vector<sampleFrame>::iterator;
|
||||
using const_iterator = std::vector<sampleFrame>::const_iterator;
|
||||
using difference_type = std::vector<sampleFrame>::difference_type;
|
||||
using size_type = std::vector<sampleFrame>::size_type;
|
||||
using reverse_iterator = std::vector<sampleFrame>::reverse_iterator;
|
||||
using const_reverse_iterator = std::vector<sampleFrame>::const_reverse_iterator;
|
||||
using value_type = SampleFrame;
|
||||
using reference = SampleFrame&;
|
||||
using const_reference = const SampleFrame&;
|
||||
using iterator = std::vector<SampleFrame>::iterator;
|
||||
using const_iterator = std::vector<SampleFrame>::const_iterator;
|
||||
using difference_type = std::vector<SampleFrame>::difference_type;
|
||||
using size_type = std::vector<SampleFrame>::size_type;
|
||||
using reverse_iterator = std::vector<SampleFrame>::reverse_iterator;
|
||||
using const_reverse_iterator = std::vector<SampleFrame>::const_reverse_iterator;
|
||||
|
||||
SampleBuffer() = default;
|
||||
explicit SampleBuffer(const QString& audioFile);
|
||||
SampleBuffer(const QString& base64, int sampleRate);
|
||||
SampleBuffer(std::vector<sampleFrame> data, int sampleRate);
|
||||
SampleBuffer(std::vector<SampleFrame> data, int sampleRate);
|
||||
SampleBuffer(
|
||||
const sampleFrame* data, size_t numFrames, int sampleRate = Engine::audioEngine()->outputSampleRate());
|
||||
const SampleFrame* data, size_t numFrames, int sampleRate = Engine::audioEngine()->outputSampleRate());
|
||||
|
||||
friend void swap(SampleBuffer& first, SampleBuffer& second) noexcept;
|
||||
auto toBase64() const -> QString;
|
||||
@@ -82,14 +82,14 @@ public:
|
||||
auto crbegin() const -> const_reverse_iterator { return m_data.crbegin(); }
|
||||
auto crend() const -> const_reverse_iterator { return m_data.crend(); }
|
||||
|
||||
auto data() const -> const sampleFrame* { return m_data.data(); }
|
||||
auto data() const -> const SampleFrame* { return m_data.data(); }
|
||||
auto size() const -> size_type { return m_data.size(); }
|
||||
auto empty() const -> bool { return m_data.empty(); }
|
||||
|
||||
static auto emptyBuffer() -> std::shared_ptr<const SampleBuffer>;
|
||||
|
||||
private:
|
||||
std::vector<sampleFrame> m_data;
|
||||
std::vector<SampleFrame> m_data;
|
||||
QString m_audioFile;
|
||||
sample_rate_t m_sampleRate = Engine::audioEngine()->outputSampleRate();
|
||||
};
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "lmms_basics.h"
|
||||
#include "SampleFrame.h"
|
||||
|
||||
namespace lmms {
|
||||
class SampleDecoder
|
||||
@@ -39,7 +40,7 @@ class SampleDecoder
|
||||
public:
|
||||
struct Result
|
||||
{
|
||||
std::vector<sampleFrame> data;
|
||||
std::vector<SampleFrame> data;
|
||||
int sampleRate;
|
||||
};
|
||||
|
||||
|
||||
230
include/SampleFrame.h
Normal file
230
include/SampleFrame.h
Normal file
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* SampleFrame.h - Representation of a stereo sample
|
||||
*
|
||||
* Copyright (c) 2004-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2024- Michael Gregorius
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LMMS_SAMPLEFRAME_H
|
||||
#define LMMS_SAMPLEFRAME_H
|
||||
|
||||
#include "lmms_basics.h"
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
|
||||
class SampleFrame
|
||||
{
|
||||
public:
|
||||
SampleFrame() : SampleFrame(0., 0.)
|
||||
{
|
||||
}
|
||||
|
||||
explicit SampleFrame(sample_t value) : SampleFrame(value, value)
|
||||
{
|
||||
}
|
||||
|
||||
SampleFrame(sample_t left, sample_t right) :
|
||||
m_samples({ left, right })
|
||||
{
|
||||
}
|
||||
|
||||
sample_t* data()
|
||||
{
|
||||
return m_samples.data();
|
||||
}
|
||||
|
||||
const sample_t* data() const
|
||||
{
|
||||
return m_samples.data();
|
||||
}
|
||||
|
||||
sample_t& left()
|
||||
{
|
||||
return m_samples[0];
|
||||
}
|
||||
|
||||
const sample_t& left() const
|
||||
{
|
||||
return m_samples[0];
|
||||
}
|
||||
|
||||
void setLeft(const sample_t& value)
|
||||
{
|
||||
m_samples[0] = value;
|
||||
}
|
||||
|
||||
sample_t& right()
|
||||
{
|
||||
return m_samples[1];
|
||||
}
|
||||
|
||||
const sample_t& right() const
|
||||
{
|
||||
return m_samples[1];
|
||||
}
|
||||
|
||||
void setRight(const sample_t& value)
|
||||
{
|
||||
m_samples[1] = value;
|
||||
}
|
||||
|
||||
sample_t& operator[](size_t index)
|
||||
{
|
||||
return m_samples[index];
|
||||
}
|
||||
|
||||
const sample_t& operator[](size_t index) const
|
||||
{
|
||||
return m_samples[index];
|
||||
}
|
||||
|
||||
SampleFrame operator+(const SampleFrame& other) const
|
||||
{
|
||||
return SampleFrame(left() + other.left(), right() + other.right());
|
||||
}
|
||||
|
||||
SampleFrame& operator+=(const SampleFrame& other)
|
||||
{
|
||||
auto & l = left();
|
||||
auto & r = right();
|
||||
|
||||
l += other.left();
|
||||
r += other.right();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
SampleFrame operator*(float value) const
|
||||
{
|
||||
return SampleFrame(left() * value, right() * value);
|
||||
}
|
||||
|
||||
SampleFrame& operator*=(float value)
|
||||
{
|
||||
setLeft(left() * value);
|
||||
setRight(right() * value);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
SampleFrame operator*(const SampleFrame& other) const
|
||||
{
|
||||
return SampleFrame(left() * other.left(), right() * other.right());
|
||||
}
|
||||
|
||||
void operator*=(const SampleFrame& other)
|
||||
{
|
||||
left() *= other.left();
|
||||
right() *= other.right();
|
||||
}
|
||||
|
||||
sample_t sumOfSquaredAmplitudes() const
|
||||
{
|
||||
return left() * left() + right() * right();
|
||||
}
|
||||
|
||||
SampleFrame abs() const
|
||||
{
|
||||
return SampleFrame{std::abs(this->left()), std::abs(this->right())};
|
||||
}
|
||||
|
||||
SampleFrame absMax(const SampleFrame& other)
|
||||
{
|
||||
const auto a = abs();
|
||||
const auto b = other.abs();
|
||||
|
||||
return SampleFrame(std::max(a.left(), b.left()), std::max(a.right(), b.right()));
|
||||
}
|
||||
|
||||
sample_t average() const
|
||||
{
|
||||
return (left() + right()) / 2;
|
||||
}
|
||||
|
||||
void clamp(sample_t low, sample_t high)
|
||||
{
|
||||
auto & l = left();
|
||||
l = std::clamp(l, low, high);
|
||||
|
||||
auto & r = right();
|
||||
r = std::clamp(r, low, high);
|
||||
}
|
||||
|
||||
bool containsInf() const
|
||||
{
|
||||
return std::isinf(left()) || std::isinf(right());
|
||||
}
|
||||
|
||||
bool containsNaN() const
|
||||
{
|
||||
return std::isnan(left()) || std::isnan(right());
|
||||
}
|
||||
|
||||
private:
|
||||
std::array<sample_t, DEFAULT_CHANNELS> m_samples;
|
||||
};
|
||||
|
||||
inline void zeroSampleFrames(SampleFrame* buffer, size_t frames)
|
||||
{
|
||||
// The equivalent of the following operation which yields compiler warnings
|
||||
// memset(buffer, 0, sizeof(SampleFrame) * frames);
|
||||
|
||||
std::fill(buffer, buffer + frames, SampleFrame());
|
||||
}
|
||||
|
||||
inline SampleFrame getAbsPeakValues(SampleFrame* buffer, size_t frames)
|
||||
{
|
||||
SampleFrame peaks;
|
||||
|
||||
for (f_cnt_t i = 0; i < frames; ++i)
|
||||
{
|
||||
peaks = peaks.absMax(buffer[i]);
|
||||
}
|
||||
|
||||
return peaks;
|
||||
}
|
||||
|
||||
inline void copyToSampleFrames(SampleFrame* target, const float* source, size_t frames)
|
||||
{
|
||||
for (size_t i = 0; i < frames; ++i)
|
||||
{
|
||||
target[i].setLeft(source[2*i]);
|
||||
target[i].setRight(source[2*i + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
inline void copyFromSampleFrames(float* target, const SampleFrame* source, size_t frames)
|
||||
{
|
||||
for (size_t i = 0; i < frames; ++i)
|
||||
{
|
||||
target[2*i] = source[i].left();
|
||||
target[2*i + 1] = source[i].right();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace lmms
|
||||
|
||||
#endif // LMMS_SAMPLEFRAME_H
|
||||
@@ -55,7 +55,7 @@ public:
|
||||
}
|
||||
|
||||
|
||||
void play( sampleFrame * buffer ) override;
|
||||
void play( SampleFrame* buffer ) override;
|
||||
bool isFinished() const override;
|
||||
|
||||
bool isFromTrack( const Track * _track ) const override;
|
||||
|
||||
@@ -48,7 +48,7 @@ public:
|
||||
SampleRecordHandle(SampleClip* clip, TimePos startRecordTimeOffset);
|
||||
~SampleRecordHandle() override;
|
||||
|
||||
void play( sampleFrame * _working_buffer ) override;
|
||||
void play( SampleFrame* _working_buffer ) override;
|
||||
bool isFinished() const override;
|
||||
|
||||
bool isFromTrack( const Track * _track ) const override;
|
||||
@@ -58,10 +58,10 @@ public:
|
||||
|
||||
|
||||
private:
|
||||
virtual void writeBuffer( const sampleFrame * _ab,
|
||||
virtual void writeBuffer( const SampleFrame* _ab,
|
||||
const f_cnt_t _frames );
|
||||
|
||||
using bufferList = QList<QPair<sampleFrame*, f_cnt_t>>;
|
||||
using bufferList = QList<QPair<SampleFrame*, f_cnt_t>>;
|
||||
bufferList m_buffers;
|
||||
f_cnt_t m_framesRecorded;
|
||||
TimePos m_minLength;
|
||||
|
||||
@@ -36,7 +36,7 @@ class LMMS_EXPORT SampleWaveform
|
||||
public:
|
||||
struct Parameters
|
||||
{
|
||||
const sampleFrame* buffer;
|
||||
const SampleFrame* buffer;
|
||||
size_t size;
|
||||
float amplification;
|
||||
bool reversed;
|
||||
|
||||
@@ -43,7 +43,7 @@ public:
|
||||
|
||||
virtual ~SweepOscillator() = default;
|
||||
|
||||
void update( sampleFrame* buf, const fpp_t frames, const float freq1, const float freq2, const float sampleRate )
|
||||
void update( SampleFrame* buf, const fpp_t frames, const float freq1, const float freq2, const float sampleRate )
|
||||
{
|
||||
const float df = freq2 - freq1;
|
||||
for( fpp_t frame = 0; frame < frames; ++frame )
|
||||
|
||||
@@ -31,17 +31,10 @@
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#include <mingw.condition_variable.h>
|
||||
#include <mingw.future.h>
|
||||
#include <mingw.mutex.h>
|
||||
#include <mingw.thread.h>
|
||||
#else
|
||||
#include <condition_variable>
|
||||
#include <future>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#endif
|
||||
|
||||
namespace lmms {
|
||||
//! A thread pool that can be used for asynchronous processing.
|
||||
|
||||
@@ -33,6 +33,9 @@
|
||||
#include <cstdint>
|
||||
#include <array>
|
||||
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
namespace lmms
|
||||
{
|
||||
@@ -48,7 +51,7 @@ using int_sample_t = int16_t; // 16-bit-int-sample
|
||||
using sample_rate_t = uint32_t; // sample-rate
|
||||
using fpp_t = int16_t; // frames per period (0-16384)
|
||||
using f_cnt_t = int32_t; // standard frame-count
|
||||
using ch_cnt_t = uint8_t; // channel-count (0-SURROUND_CHANNELS)
|
||||
using ch_cnt_t = uint8_t; // channel-count (0-DEFAULT_CHANNELS)
|
||||
using bpm_t = uint16_t; // tempo (MIN_BPM to MAX_BPM)
|
||||
using bitrate_t = uint16_t; // bitrate in kbps
|
||||
using mix_ch_t = uint16_t; // Mixer-channel (0 to MAX_CHANNEL)
|
||||
@@ -109,14 +112,6 @@ inline bool typeInfo<float>::isEqual( float x, float y )
|
||||
|
||||
constexpr ch_cnt_t DEFAULT_CHANNELS = 2;
|
||||
|
||||
constexpr ch_cnt_t SURROUND_CHANNELS =
|
||||
#define LMMS_DISABLE_SURROUND
|
||||
#ifndef LMMS_DISABLE_SURROUND
|
||||
4;
|
||||
#else
|
||||
2;
|
||||
#endif
|
||||
|
||||
constexpr char LADSPA_PATH_SEPERATOR =
|
||||
#ifdef LMMS_BUILD_WIN32
|
||||
';';
|
||||
@@ -126,11 +121,6 @@ constexpr char LADSPA_PATH_SEPERATOR =
|
||||
|
||||
|
||||
|
||||
using sampleFrame = std::array<sample_t, DEFAULT_CHANNELS>;
|
||||
using surroundSampleFrame = std::array<sample_t, SURROUND_CHANNELS>;
|
||||
constexpr std::size_t LMMS_ALIGN_SIZE = 16;
|
||||
|
||||
|
||||
#define LMMS_STRINGIFY(s) LMMS_STR(s)
|
||||
#define LMMS_STR(PN) #PN
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ constexpr long double LD_PI_R = 1.0 / LD_PI;
|
||||
constexpr long double LD_PI_SQR = LD_PI * LD_PI;
|
||||
constexpr long double LD_E = 2.71828182845904523536028747135266249775724709369995;
|
||||
constexpr long double LD_E_R = 1.0 / LD_E;
|
||||
constexpr long double LD_SQRT_2 = 1.41421356237309504880168872420969807856967187537695;
|
||||
|
||||
constexpr double D_PI = (double) LD_PI;
|
||||
constexpr double D_2PI = (double) LD_2PI;
|
||||
@@ -44,6 +45,7 @@ constexpr double D_PI_R = (double) LD_PI_R;
|
||||
constexpr double D_PI_SQR = (double) LD_PI_SQR;
|
||||
constexpr double D_E = (double) LD_E;
|
||||
constexpr double D_E_R = (double) LD_E_R;
|
||||
constexpr double D_SQRT_2 = (double) LD_SQRT_2;
|
||||
|
||||
constexpr float F_PI = (float) LD_PI;
|
||||
constexpr float F_2PI = (float) LD_2PI;
|
||||
@@ -52,6 +54,7 @@ constexpr float F_PI_R = (float) LD_PI_R;
|
||||
constexpr float F_PI_SQR = (float) LD_PI_SQR;
|
||||
constexpr float F_E = (float) LD_E;
|
||||
constexpr float F_E_R = (float) LD_E_R;
|
||||
constexpr float F_SQRT_2 = (float) LD_SQRT_2;
|
||||
|
||||
// Microtuner
|
||||
constexpr unsigned int MaxScaleCount = 10; //!< number of scales per project
|
||||
|
||||
Reference in New Issue
Block a user