Simplify sample frame operations (make it a class) (#7156)

* Remove the struct StereoSample

Remove the struct `StereoSample`. Let `AudioEngine::getPeakValues` return a `sampleFrame` instead.

Adjust the calls in `Mixer`  and `Oscilloscope`.

* Simplify AudioEngine::getPeakValues

* Remove surroundSampleFrame

Some code assumes that `surroundSampleFrame` is interchangeable with `sampleFrame`. Thus, if the line `#define LMMS_DISABLE_SURROUND` is commented out in `lmms_basics.h` then the code does not compile anymore because `surroundSampleFrame` now is defined to be an array with four values instead of two. There also does not seem to be any support for surround sound (four channels instead of two) in the application. The faders and mixers do not seem to support more that two channels and the instruments and effects all expect a `sampleFrame`, i.e. stereo channels. It therefore makes sense to remove the "feature" because it also hinders the improvement of `sampleFrame`, e.g. by making it a class with some convenience methods that act on `sampleFrame` instances.

All occurrences of `surroundSampleFrame` are replaced with `sampleFrame`.

The version of `BufferManager::clear` that takes a `surroundSampleFrame` is removed completely.

The define `SURROUND_CHANNELS` is removed. All its occurrences are replaced with `DEFAULT_CHANNELS`.

Most of the audio devices classes, i.e. classes that inherit from `AudioDevice`, now clamp the configuration parameter between two values of `DEFAULT_CHANNELS`. This can be improved/streamlined later.

`BYTES_PER_SURROUND_FRAME` has been removed as it was not used anywhere anyway.

* Make sampleFrame a class

Make `sampleFrame` a class with several convenience methods. As a first step and demonstration adjust the follow methods to make use of the new functionality:
* `AudioEngine::getPeakValues`: Much more concise now.
* `lmms::MixHelpers::sanitize`: Better structure, better readable, less dereferencing and juggling with indices.
* `AddOp`, `AddMultipliedOp`, `multiply`: Make use of operators. Might become superfluous in the future.

* More operators and methods for sampleFrame

Add some more operators and methods to `sampleFrame`:
* Constructor which initializes both channels from a single sample value
* Assignment operator from a single sample value
* Addition/multiplication operators
* Scalar product

Adjust some more plugins to the new functionality of `sampleFrame`.

* Adjust DelayEffect to methods in sampleFrame

* Use composition instead of inheritance

Using inheritance was the quickest way to enable adding methods to `sampleFrame` without having to reimpement much of `std::array`s interface.

This is changed with this commit. The array is now a member of `sampleFrame` and the interface is extended with the necessary methods `data` and the index operator.

An `average` method was added so that no iterators need to be implemented (see changes in `SampleWaveform.cpp`).

* Apply suggestions from code review

Apply Veratil's suggestions from the code review

Co-authored-by: Kevin Zander <veratil@gmail.com>

* Fix warnings: zeroing non-trivial type

Fix several warnings of the following form:

Warnung: »void* memset(void*, int, size_t)« Säubern eines Objekts von nichttrivialem Typ »class lmms::sampleFrame«; use assignment or value-initialization instead [-Wclass-memaccess]

* Remove unnecessary reinterpret_casts

Remove some unnecessary reinterpret_casts with regards to `sampleFrame` buffers.

`PlayHandle::m_playHandleBuffer` already is a `sampleFrame*` and does not need a reinterpret_cast anymore.

In `LadspaEffect::processAudioBuffer` the `QVarLengthArray` is now directly initialized as an array of `sampleFrame` instances.

I guess in both places the `sampleFrame` previously was a `surroundSampleFrame` which has been removed.

* Clean up zeroSampleFrames code

* Fix warnings in RemotePlugin

Fix some warnings related to calls to `memcpy` in conjunction with`sampleFrame` which is now a class.

Add the helper functions `copyToSampleFrames` and `copyFromSampleFrames` and use them. The first function copies data from a `float` buffer into a `sampleFrame` buffer and the second copies vice versa.

* Rename "sampleFrame" to "SampleFrame"

Uppercase the name of `sampleFrame` so that it uses UpperCamelCase convention.

* Move SampleFrame into its own file

Move the class `SampleFrame` into its own class and remove it from `lmms_basics.h`.

Add forward includes to all headers where possible or include the `SampleFrame` header if it's not just referenced but used.

Add include to all cpp files where necessary.

It's a bit surprising that the `SampleFrame` header does not need to be included much more often in the implementation/cpp files. This is an indicator that it seems to be included via an include chain that at one point includes one of the headers where an include instead of a forward declaration had to be added in this commit.

* Return reference for += and *=

Return a reference for the compound assignment operators `+=` and `-=`.

* Explicit float constructor

Make the  constructor that takes a `float` explicit.

Remove the assignment operator that takes a `float`. Clients must use the
explicit `float` constructor and assign the result.

Adjust the code in "BitInvader" accordingly.

* Use std::fill in zeroSampleFrames

* Use zeroSampleFrames in sanitize

* Replace max with absMax

Replace `SampleFrame::max` with `SampleFrame::absMax`.

Use `absMax` in `DelayEffect::processAudioBuffer`. This should also fix
a buggy implementation of the peak computation.

Add the function `getAbsPeakValues`. It  computes the absolute peak
values for a buffer.

Remove `AudioEngine::getPeakValues`. It's not really the business of the
audio engine. Let `Mixer` and `Oscilloscope` use `getAbsPeakValues`.

* Replace scalarProduct

Replace the rather mathematical method `scalarProduct` with
`sumOfSquaredAmplitudes`. It was always called on itself anyway.

* Remove comment/TODO

* Simplify sanitize

Simplify the `sanitize` function by getting rid of the `bool found` and
by zeroing the buffer as soon as a problem is found.

* Put pointer symbols next to type

* Code review adjustments

* Remove "#pragme once"
* Adjust name of include guard
* Remove superfluous includes (leftovers from previous code changes)

---------

Co-authored-by: Kevin Zander <veratil@gmail.com>
This commit is contained in:
Michael Gregorius
2024-06-30 20:21:19 +02:00
committed by GitHub
parent a0fbd7e7b4
commit 286e62adf5
199 changed files with 879 additions and 668 deletions

View File

@@ -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;
};

View File

@@ -94,7 +94,7 @@ private:
while( true )
{
timer.reset();
const surroundSampleFrame* b = audioEngine()->nextBuffer();
const SampleFrame* b = audioEngine()->nextBuffer();
if( !b )
{
break;

View File

@@ -38,6 +38,7 @@
#include <vector>
#include "lmms_basics.h"
#include "SampleFrame.h"
#include "LocklessList.h"
#include "FifoBuffer.h"
#include "AudioEngineProfiler.h"
@@ -58,8 +59,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;
@@ -267,15 +267,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
@@ -283,9 +274,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 ];
}
@@ -295,7 +286,7 @@ public:
return m_inputBufferFrames[ m_inputBufferRead ];
}
inline const surroundSampleFrame * nextBuffer()
inline const SampleFrame* nextBuffer()
{
return hasFifoWriter() ? m_fifo->read() : renderNextBuffer();
}
@@ -321,11 +312,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
{
@@ -342,7 +333,7 @@ private:
void run() override;
void write( surroundSampleFrame * buffer );
void write(SampleFrame* buffer);
} ;
@@ -361,7 +352,7 @@ private:
void renderStageEffects();
void renderStageMix();
const surroundSampleFrame * renderNextBuffer();
const SampleFrame* renderNextBuffer();
void swapBuffers();
@@ -375,14 +366,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;
std::unique_ptr<surroundSampleFrame[]> m_outputBufferRead;
std::unique_ptr<surroundSampleFrame[]> m_outputBufferWrite;
std::unique_ptr<SampleFrame[]> m_outputBufferRead;
std::unique_ptr<SampleFrame[]> m_outputBufferWrite;
// worker thread stuff
std::vector<AudioEngineWorkerThread *> m_workers;

View File

@@ -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();

View File

@@ -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();

View File

@@ -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();

View File

@@ -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();

View File

@@ -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;

View File

@@ -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;

View File

@@ -150,7 +150,7 @@ private:
bool m_wasPAInitError;
surroundSampleFrame * m_outBuf;
SampleFrame* m_outBuf;
int m_outBufPos;
int m_outBufSize;

View File

@@ -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;
} ;

View File

@@ -85,7 +85,7 @@ private:
SDL_AudioSpec m_audioHandle;
surroundSampleFrame * m_outBuf;
SampleFrame* m_outBuf;
#ifdef LMMS_HAVE_SDL2
size_t m_currentBufferFramePos;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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 );

View File

@@ -107,7 +107,7 @@ public:
return &m_controls;
}
bool processAudioBuffer( sampleFrame *, const fpp_t ) override
bool processAudioBuffer( SampleFrame*, const fpp_t ) override
{
return false;
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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();

View File

@@ -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;

View File

@@ -41,7 +41,7 @@ public:
~InstrumentPlayHandle() override = default;
void play(sampleFrame * working_buffer) override;
void play(SampleFrame* working_buffer) override;
bool isFinished() const override
{

View File

@@ -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

View File

@@ -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

View File

@@ -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);

View File

@@ -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; }

View File

@@ -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);

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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>

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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 );

View File

@@ -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

View File

@@ -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;
};

View File

@@ -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:

View File

@@ -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();
};

View File

@@ -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;
};

229
include/SampleFrame.h Normal file
View File

@@ -0,0 +1,229 @@
/*
* 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>
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, fpp_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, fpp_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, fpp_t frames)
{
for (fpp_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, fpp_t frames)
{
for (fpp_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

View File

@@ -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;

View File

@@ -48,7 +48,7 @@ public:
SampleRecordHandle( SampleClip* clip );
~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;

View File

@@ -36,7 +36,7 @@ class LMMS_EXPORT SampleWaveform
public:
struct Parameters
{
const sampleFrame* buffer;
const SampleFrame* buffer;
size_t size;
float amplification;
bool reversed;

View File

@@ -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 )

View File

@@ -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,10 +121,6 @@ constexpr char LADSPA_PATH_SEPERATOR =
using sampleFrame = std::array<sample_t, DEFAULT_CHANNELS>;
using surroundSampleFrame = std::array<sample_t, SURROUND_CHANNELS>;
#define LMMS_STRINGIFY(s) LMMS_STR(s)
#define LMMS_STR(PN) #PN

View File

@@ -57,7 +57,7 @@ AmplifierEffect::AmplifierEffect(Model* parent, const Descriptor::SubPluginFeatu
}
bool AmplifierEffect::processAudioBuffer(sampleFrame* buf, const fpp_t frames)
bool AmplifierEffect::processAudioBuffer(SampleFrame* buf, const fpp_t frames)
{
if (!isEnabled() || !isRunning()) { return false ; }
@@ -80,14 +80,14 @@ bool AmplifierEffect::processAudioBuffer(sampleFrame* buf, const fpp_t frames)
const float panLeft = std::min(1.0f, 1.0f - pan);
const float panRight = std::min(1.0f, 1.0f + pan);
auto s = std::array{buf[f][0], buf[f][1]};
auto& currentFrame = buf[f];
s[0] *= volume * left * panLeft;
s[1] *= volume * right * panRight;
const auto s = currentFrame * SampleFrame(left * panLeft, right * panRight) * volume;
buf[f][0] = d * buf[f][0] + w * s[0];
buf[f][1] = d * buf[f][1] + w * s[1];
outSum += buf[f][0] * buf[f][0] + buf[f][1] * buf[f][1];
// Dry/wet mix
currentFrame = currentFrame * d + s * w;
outSum += currentFrame.sumOfSquaredAmplitudes();
}
checkGate(outSum / frames);

View File

@@ -37,7 +37,7 @@ class AmplifierEffect : public Effect
public:
AmplifierEffect(Model* parent, const Descriptor::SubPluginFeatures::Key* key);
~AmplifierEffect() override = default;
bool processAudioBuffer(sampleFrame* buf, const fpp_t frames) override;
bool processAudioBuffer(SampleFrame* buf, const fpp_t frames) override;
EffectControls* controls() override
{

View File

@@ -105,7 +105,7 @@ AudioFileProcessor::AudioFileProcessor( InstrumentTrack * _instrument_track ) :
void AudioFileProcessor::playNote( NotePlayHandle * _n,
sampleFrame * _working_buffer )
SampleFrame* _working_buffer )
{
const fpp_t frames = _n->framesLeftForCurrentPeriod();
const f_cnt_t offset = _n->noteOffset();
@@ -165,7 +165,7 @@ void AudioFileProcessor::playNote( NotePlayHandle * _n,
}
else
{
memset( _working_buffer, 0, ( frames + offset ) * sizeof( sampleFrame ) );
zeroSampleFrames(_working_buffer, frames + offset);
emit isPlaying( 0 );
}
}

View File

@@ -44,7 +44,7 @@ public:
AudioFileProcessor( InstrumentTrack * _instrument_track );
void playNote( NotePlayHandle * _n,
sampleFrame * _working_buffer ) override;
SampleFrame* _working_buffer ) override;
void deleteNotePluginData( NotePlayHandle * _n ) override;
void saveSettings(QDomDocument& doc, QDomElement& elem) override;

View File

@@ -69,7 +69,7 @@ BassBoosterEffect::BassBoosterEffect( Model* parent, const Descriptor::SubPlugin
bool BassBoosterEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
bool BassBoosterEffect::processAudioBuffer( SampleFrame* buf, const fpp_t frames )
{
if( !isEnabled() || !isRunning () )
{
@@ -91,23 +91,19 @@ bool BassBoosterEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames
const float d = dryLevel();
const float w = wetLevel();
for( fpp_t f = 0; f < frames; ++f )
for (fpp_t f = 0; f < frames; ++f)
{
float gain = const_gain;
if (gainBuffer) {
//process period using sample exact data
gain = gainBuffer->value( f );
}
//float gain = gainBuffer ? gainBuffer[f] : gain;
m_bbFX.leftFX().setGain( gain );
m_bbFX.rightFX().setGain( gain);
auto& currentFrame = buf[f];
auto s = std::array{buf[f][0], buf[f][1]};
m_bbFX.nextSample( s[0], s[1] );
// Process copy of current sample frame
m_bbFX.setGain(gainBuffer ? gainBuffer->value(f) : const_gain);
auto s = currentFrame;
m_bbFX.nextSample(s);
buf[f][0] = d * buf[f][0] + w * s[0];
buf[f][1] = d * buf[f][1] + w * s[1];
outSum += buf[f][0] * buf[f][0] + buf[f][1] * buf[f][1];
// Dry/wet mix
currentFrame = currentFrame * d + s * w;
outSum += currentFrame.sumOfSquaredAmplitudes();
}
checkGate( outSum / frames );

View File

@@ -38,7 +38,7 @@ class BassBoosterEffect : public Effect
public:
BassBoosterEffect( Model* parent, const Descriptor::SubPluginFeatures::Key* key );
~BassBoosterEffect() override = default;
bool processAudioBuffer( sampleFrame* buf, const fpp_t frames ) override;
bool processAudioBuffer( SampleFrame* buf, const fpp_t frames ) override;
EffectControls* controls() override
{

View File

@@ -256,7 +256,7 @@ QString BitInvader::nodeName() const
void BitInvader::playNote( NotePlayHandle * _n,
sampleFrame * _working_buffer )
SampleFrame* _working_buffer )
{
if (!_n->m_pluginData)
{
@@ -274,11 +274,7 @@ void BitInvader::playNote( NotePlayHandle * _n,
auto ps = static_cast<BSynth*>(_n->m_pluginData);
for( fpp_t frame = offset; frame < frames + offset; ++frame )
{
const sample_t cur = ps->nextStringSample( m_graph.length() );
for( ch_cnt_t chnl = 0; chnl < DEFAULT_CHANNELS; ++chnl )
{
_working_buffer[frame][chnl] = cur;
}
_working_buffer[frame] = SampleFrame(ps->nextStringSample(m_graph.length()));
}
applyRelease( _working_buffer, _n );

View File

@@ -75,7 +75,7 @@ public:
~BitInvader() override = default;
void playNote( NotePlayHandle * _n,
sampleFrame * _working_buffer ) override;
SampleFrame* _working_buffer ) override;
void deleteNotePluginData( NotePlayHandle * _n ) override;

View File

@@ -62,7 +62,7 @@ BitcrushEffect::BitcrushEffect( Model * parent, const Descriptor::SubPluginFeatu
m_sampleRate( Engine::audioEngine()->outputSampleRate() ),
m_filter( m_sampleRate )
{
m_buffer = new sampleFrame[Engine::audioEngine()->framesPerPeriod() * OS_RATE];
m_buffer = new SampleFrame[Engine::audioEngine()->framesPerPeriod() * OS_RATE];
m_filter.setLowpass( m_sampleRate * ( CUTOFF_RATIO * OS_RATIO ) );
m_needsUpdate = true;
@@ -100,7 +100,7 @@ inline float BitcrushEffect::noise( float amt )
return fastRandf( amt * 2.0f ) - amt;
}
bool BitcrushEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
bool BitcrushEffect::processAudioBuffer( SampleFrame* buf, const fpp_t frames )
{
if( !isEnabled() || !isRunning () )
{

View File

@@ -41,7 +41,7 @@ class BitcrushEffect : public Effect
public:
BitcrushEffect( Model* parent, const Descriptor::SubPluginFeatures::Key* key );
~BitcrushEffect() override;
bool processAudioBuffer( sampleFrame* buf, const fpp_t frames ) override;
bool processAudioBuffer( SampleFrame* buf, const fpp_t frames ) override;
EffectControls* controls() override
{
@@ -55,7 +55,7 @@ private:
BitcrushControls m_controls;
sampleFrame * m_buffer;
SampleFrame* m_buffer;
float m_sampleRate;
StereoLinkwitzRiley m_filter;

View File

@@ -495,11 +495,11 @@ void CarlaInstrument::loadSettings(const QDomElement& elem)
#endif
}
void CarlaInstrument::play(sampleFrame* workingBuffer)
void CarlaInstrument::play(SampleFrame* workingBuffer)
{
const uint bufsize = Engine::audioEngine()->framesPerPeriod();
std::memset(workingBuffer, 0, sizeof(sample_t)*bufsize*DEFAULT_CHANNELS);
zeroSampleFrames(workingBuffer, bufsize);
if (fHandle == nullptr)
{

View File

@@ -193,7 +193,7 @@ public:
QString nodeName() const override;
void saveSettings(QDomDocument& doc, QDomElement& parent) override;
void loadSettings(const QDomElement& elem) override;
void play(sampleFrame* workingBuffer) override;
void play(SampleFrame* workingBuffer) override;
bool handleMidiEvent(const MidiEvent& event, const TimePos& time, f_cnt_t offset) override;
gui::PluginView* instantiateView(QWidget* parent) override;

View File

@@ -233,7 +233,7 @@ void CompressorEffect::calcMix()
bool CompressorEffect::processAudioBuffer(sampleFrame* buf, const fpp_t frames)
bool CompressorEffect::processAudioBuffer(SampleFrame* buf, const fpp_t frames)
{
if (!isEnabled() || !isRunning())
{

View File

@@ -43,7 +43,7 @@ class CompressorEffect : public Effect
public:
CompressorEffect(Model* parent, const Descriptor::SubPluginFeatures::Key* key);
~CompressorEffect() override = default;
bool processAudioBuffer(sampleFrame* buf, const fpp_t frames) override;
bool processAudioBuffer(SampleFrame* buf, const fpp_t frames) override;
EffectControls* controls() override
{
@@ -105,7 +105,7 @@ private:
float m_coeffPrecalc;
sampleFrame m_maxLookaheadVal;
SampleFrame m_maxLookaheadVal;
int m_maxLookaheadTimer[2] = {1, 1};

View File

@@ -64,9 +64,9 @@ CrossoverEQEffect::CrossoverEQEffect( Model* parent, const Descriptor::SubPlugin
m_hp4( m_sampleRate ),
m_needsUpdate( true )
{
m_tmp2 = new sampleFrame[Engine::audioEngine()->framesPerPeriod()];
m_tmp1 = new sampleFrame[Engine::audioEngine()->framesPerPeriod()];
m_work = new sampleFrame[Engine::audioEngine()->framesPerPeriod()];
m_tmp2 = new SampleFrame[Engine::audioEngine()->framesPerPeriod()];
m_tmp1 = new SampleFrame[Engine::audioEngine()->framesPerPeriod()];
m_work = new SampleFrame[Engine::audioEngine()->framesPerPeriod()];
}
CrossoverEQEffect::~CrossoverEQEffect()
@@ -89,7 +89,7 @@ void CrossoverEQEffect::sampleRateChanged()
}
bool CrossoverEQEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
bool CrossoverEQEffect::processAudioBuffer( SampleFrame* buf, const fpp_t frames )
{
if( !isEnabled() || !isRunning () )
{
@@ -139,7 +139,7 @@ bool CrossoverEQEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames
m_needsUpdate = false;
memset( m_work, 0, sizeof( sampleFrame ) * frames );
zeroSampleFrames(m_work, frames);
// run temp bands
for( int f = 0; f < frames; ++f )

View File

@@ -40,7 +40,7 @@ class CrossoverEQEffect : public Effect
public:
CrossoverEQEffect( Model* parent, const Descriptor::SubPluginFeatures::Key* key );
~CrossoverEQEffect() override;
bool processAudioBuffer( sampleFrame* buf, const fpp_t frames ) override;
bool processAudioBuffer( SampleFrame* buf, const fpp_t frames ) override;
EffectControls* controls() override
{
@@ -69,9 +69,9 @@ private:
StereoLinkwitzRiley m_hp3;
StereoLinkwitzRiley m_hp4;
sampleFrame * m_tmp1;
sampleFrame * m_tmp2;
sampleFrame * m_work;
SampleFrame* m_tmp1;
SampleFrame* m_tmp2;
SampleFrame* m_work;
bool m_needsUpdate;

View File

@@ -81,7 +81,7 @@ DelayEffect::~DelayEffect()
bool DelayEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
bool DelayEffect::processAudioBuffer( SampleFrame* buf, const fpp_t frames )
{
if( !isEnabled() || !isRunning () )
{
@@ -91,9 +91,8 @@ bool DelayEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
const float sr = Engine::audioEngine()->outputSampleRate();
const float d = dryLevel();
const float w = wetLevel();
auto dryS = std::array<sample_t, 2>{};
float lPeak = 0.0;
float rPeak = 0.0;
SampleFrame peak;
float length = m_delayControls.m_delayTimeModel.value();
float amplitude = m_delayControls.m_lfoAmountModel.value() * sr;
float lfoTime = 1.0 / m_delayControls.m_lfoTimeModel.value();
@@ -116,26 +115,28 @@ bool DelayEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
m_outGain = dbfsToAmp( m_delayControls.m_outGainModel.value() );
}
for( fpp_t f = 0; f < frames; ++f )
for (fpp_t f = 0; f < frames; ++f)
{
dryS[0] = buf[f][0];
dryS[1] = buf[f][1];
auto& currentFrame = buf[f];
const auto dryS = currentFrame;
// Prepare delay for current sample
m_delay->setFeedback( *feedbackPtr );
m_lfo->setFrequency( *lfoTimePtr );
m_currentLength = static_cast<int>(*lengthPtr * Engine::audioEngine()->outputSampleRate());
m_delay->setLength( m_currentLength + ( *amplitudePtr * ( float )m_lfo->tick() ) );
m_delay->tick( buf[f] );
buf[f][0] *= m_outGain;
buf[f][1] *= m_outGain;
// Process the wet signal
m_delay->tick( currentFrame );
currentFrame *= m_outGain;
lPeak = buf[f][0] > lPeak ? buf[f][0] : lPeak;
rPeak = buf[f][1] > rPeak ? buf[f][1] : rPeak;
// Calculate peak of wet signal
peak = peak.absMax(currentFrame);
buf[f][0] = ( d * dryS[0] ) + ( w * buf[f][0] );
buf[f][1] = ( d * dryS[1] ) + ( w * buf[f][1] );
outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1];
// Dry/wet mix
currentFrame = dryS * d + currentFrame * w;
outSum += currentFrame.sumOfSquaredAmplitudes();
lengthPtr += lengthInc;
amplitudePtr += amplitudeInc;
@@ -143,8 +144,8 @@ bool DelayEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
feedbackPtr += feedbackInc;
}
checkGate( outSum / frames );
m_delayControls.m_outPeakL = lPeak;
m_delayControls.m_outPeakR = rPeak;
m_delayControls.m_outPeakL = peak.left();
m_delayControls.m_outPeakR = peak.right();
return isRunning();
}

View File

@@ -39,7 +39,7 @@ class DelayEffect : public Effect
public:
DelayEffect(Model* parent , const Descriptor::SubPluginFeatures::Key* key );
~DelayEffect() override;
bool processAudioBuffer( sampleFrame* buf, const fpp_t frames ) override;
bool processAudioBuffer( SampleFrame* buf, const fpp_t frames ) override;
EffectControls* controls() override
{
return &m_delayControls;

View File

@@ -23,7 +23,9 @@
*/
#include "StereoDelay.h"
#include "lmms_basics.h"
#include "SampleFrame.h"
namespace lmms
{
@@ -55,7 +57,7 @@ StereoDelay::~StereoDelay()
void StereoDelay::tick( sampleFrame& frame )
void StereoDelay::tick( SampleFrame& frame )
{
m_writeIndex = ( m_writeIndex + 1 ) % ( int )m_maxLength;
int readIndex = m_writeIndex - static_cast<int>(m_length);
@@ -81,7 +83,7 @@ void StereoDelay::setSampleRate( int sampleRate )
}
int bufferSize = ( int )( sampleRate * m_maxTime );
m_buffer = new sampleFrame[bufferSize];
m_buffer = new SampleFrame[bufferSize];
for( int i = 0 ; i < bufferSize ; i++)
{
m_buffer[i][0] = 0.0;

View File

@@ -31,6 +31,8 @@
namespace lmms
{
class SampleFrame;
class StereoDelay
{
public:
@@ -49,11 +51,11 @@ public:
m_feedback = feedback;
}
void tick( sampleFrame& frame );
void tick( SampleFrame& frame );
void setSampleRate( int sampleRate );
private:
sampleFrame* m_buffer;
SampleFrame* m_buffer;
int m_maxLength;
float m_length;
int m_writeIndex;

View File

@@ -58,7 +58,7 @@ DispersionEffect::DispersionEffect(Model* parent, const Descriptor::SubPluginFea
}
bool DispersionEffect::processAudioBuffer(sampleFrame* buf, const fpp_t frames)
bool DispersionEffect::processAudioBuffer(SampleFrame* buf, const fpp_t frames)
{
if (!isEnabled() || !isRunning())
{

View File

@@ -41,7 +41,7 @@ class DispersionEffect : public Effect
public:
DispersionEffect(Model* parent, const Descriptor::SubPluginFeatures::Key* key);
~DispersionEffect() override = default;
bool processAudioBuffer(sampleFrame* buf, const fpp_t frames) override;
bool processAudioBuffer(SampleFrame* buf, const fpp_t frames) override;
EffectControls* controls() override
{

View File

@@ -77,7 +77,7 @@ DualFilterEffect::~DualFilterEffect()
bool DualFilterEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
bool DualFilterEffect::processAudioBuffer( SampleFrame* buf, const fpp_t frames )
{
if( !isEnabled() || !isRunning () )
{

View File

@@ -40,7 +40,7 @@ class DualFilterEffect : public Effect
public:
DualFilterEffect( Model* parent, const Descriptor::SubPluginFeatures::Key* key );
~DualFilterEffect() override;
bool processAudioBuffer( sampleFrame* buf, const fpp_t frames ) override;
bool processAudioBuffer( SampleFrame* buf, const fpp_t frames ) override;
EffectControls* controls() override
{

View File

@@ -91,7 +91,7 @@ inline void DynProcEffect::calcRelease()
}
bool DynProcEffect::processAudioBuffer( sampleFrame * _buf,
bool DynProcEffect::processAudioBuffer( SampleFrame* _buf,
const fpp_t _frames )
{
if( !isEnabled() || !isRunning () )

View File

@@ -42,7 +42,7 @@ public:
DynProcEffect( Model * _parent,
const Descriptor::SubPluginFeatures::Key * _key );
~DynProcEffect() override;
bool processAudioBuffer( sampleFrame * _buf,
bool processAudioBuffer( SampleFrame* _buf,
const fpp_t _frames ) override;
EffectControls * controls() override

View File

@@ -64,7 +64,7 @@ EqEffect::EqEffect( Model *parent, const Plugin::Descriptor::SubPluginFeatures::
bool EqEffect::processAudioBuffer( sampleFrame *buf, const fpp_t frames )
bool EqEffect::processAudioBuffer( SampleFrame* buf, const fpp_t frames )
{
const int sampleRate = Engine::audioEngine()->outputSampleRate();
@@ -157,7 +157,7 @@ bool EqEffect::processAudioBuffer( sampleFrame *buf, const fpp_t frames )
}
const float outGain = m_outGain;
sampleFrame m_inPeak = { 0, 0 };
SampleFrame m_inPeak = { 0, 0 };
if(m_eqControls.m_analyseInModel.value( true ) && outSum > 0 && m_eqControls.isViewVisible() )
{
@@ -263,7 +263,7 @@ bool EqEffect::processAudioBuffer( sampleFrame *buf, const fpp_t frames )
}
sampleFrame outPeak = { 0, 0 };
SampleFrame outPeak = { 0, 0 };
gain( buf, frames, outGain, &outPeak );
m_eqControls.m_outPeakL = m_eqControls.m_outPeakL < outPeak[0] ? outPeak[0] : m_eqControls.m_outPeakL;
m_eqControls.m_outPeakR = m_eqControls.m_outPeakR < outPeak[1] ? outPeak[1] : m_eqControls.m_outPeakR;

View File

@@ -40,12 +40,12 @@ class EqEffect : public Effect
public:
EqEffect( Model * parent , const Descriptor::SubPluginFeatures::Key * key );
~EqEffect() override = default;
bool processAudioBuffer( sampleFrame * buf, const fpp_t frames ) override;
bool processAudioBuffer( SampleFrame* buf, const fpp_t frames ) override;
EffectControls * controls() override
{
return &m_eqControls;
}
inline void gain( sampleFrame * buf, const fpp_t frames, float scale, sampleFrame * peak )
inline void gain( SampleFrame* buf, const fpp_t frames, float scale, SampleFrame* peak )
{
peak[0][0] = 0.0f; peak[0][1] = 0.0f;
for( fpp_t f = 0; f < frames; ++f )

View File

@@ -432,7 +432,7 @@ public:
virtual void processBuffer( sampleFrame* buf, const fpp_t frames )
virtual void processBuffer( SampleFrame* buf, const fpp_t frames )
{
for ( fpp_t f = 0 ; f < frames ; ++f)
{

View File

@@ -75,7 +75,7 @@ EqAnalyser::~EqAnalyser()
void EqAnalyser::analyze( sampleFrame *buf, const fpp_t frames )
void EqAnalyser::analyze( SampleFrame* buf, const fpp_t frames )
{
//only analyse if the view is visible
if ( m_active )

View File

@@ -32,6 +32,7 @@
namespace lmms
{
class SampleFrame;
const int MAX_BANDS = 2048;
class EqAnalyser
@@ -44,7 +45,7 @@ public:
bool getInProgress();
void clear();
void analyze( sampleFrame *buf, const fpp_t frames );
void analyze( SampleFrame* buf, const fpp_t frames );
float getEnergy() const;
int getSampleRate() const;

View File

@@ -90,7 +90,7 @@ FlangerEffect::~FlangerEffect()
bool FlangerEffect::processAudioBuffer( sampleFrame *buf, const fpp_t frames )
bool FlangerEffect::processAudioBuffer( SampleFrame* buf, const fpp_t frames )
{
if( !isEnabled() || !isRunning () )
{

View File

@@ -42,7 +42,7 @@ class FlangerEffect : public Effect
public:
FlangerEffect( Model* parent , const Descriptor::SubPluginFeatures::Key* key );
~FlangerEffect() override;
bool processAudioBuffer( sampleFrame *buf, const fpp_t frames ) override;
bool processAudioBuffer( SampleFrame* buf, const fpp_t frames ) override;
EffectControls* controls() override
{
return &m_flangerControls;

View File

@@ -228,7 +228,7 @@ float FreeBoyInstrument::desiredReleaseTimeMs() const
void FreeBoyInstrument::playNote(NotePlayHandle* nph, sampleFrame* workingBuffer)
void FreeBoyInstrument::playNote(NotePlayHandle* nph, SampleFrame* workingBuffer)
{
const f_cnt_t tfp = nph->totalFramesPlayed();
const int samplerate = Engine::audioEngine()->outputSampleRate();

View File

@@ -55,7 +55,7 @@ public:
FreeBoyInstrument( InstrumentTrack * _instrument_track );
~FreeBoyInstrument() override = default;
void playNote(NotePlayHandle* nph, sampleFrame* workingBuffer) override;
void playNote(NotePlayHandle* nph, SampleFrame* workingBuffer) override;
void deleteNotePluginData(NotePlayHandle* nph) override;
void saveSettings( QDomDocument & _doc, QDomElement & _parent ) override;

View File

@@ -289,7 +289,7 @@ QString GigInstrument::getCurrentPatchName()
// A key has been pressed
void GigInstrument::playNote( NotePlayHandle * _n, sampleFrame * )
void GigInstrument::playNote( NotePlayHandle * _n, SampleFrame* )
{
const float LOG440 = 2.643452676f;
@@ -320,7 +320,7 @@ void GigInstrument::playNote( NotePlayHandle * _n, sampleFrame * )
// Process the notes and output a certain number of frames (e.g. 256, set in
// the preferences)
void GigInstrument::play( sampleFrame * _working_buffer )
void GigInstrument::play( SampleFrame* _working_buffer )
{
const fpp_t frames = Engine::audioEngine()->framesPerPeriod();
const int rate = Engine::audioEngine()->outputSampleRate();
@@ -441,7 +441,7 @@ void GigInstrument::play( sampleFrame * _working_buffer )
}
// Load this note's data
sampleFrame sampleData[samples];
SampleFrame sampleData[samples];
loadSample(sample, sampleData, samples);
// Apply ADSR using a copy so if we don't use these samples when
@@ -458,7 +458,7 @@ void GigInstrument::play( sampleFrame * _working_buffer )
// Output the data resampling if needed
if( resample == true )
{
sampleFrame convertBuf[frames];
SampleFrame convertBuf[frames];
// Only output if resampling is successful (note that "used" is output)
if (sample.convertSampleRate(*sampleData, *convertBuf, samples, frames, freq_factor, used))
@@ -499,7 +499,7 @@ void GigInstrument::play( sampleFrame * _working_buffer )
void GigInstrument::loadSample( GigSample& sample, sampleFrame* sampleData, f_cnt_t samples )
void GigInstrument::loadSample( GigSample& sample, SampleFrame* sampleData, f_cnt_t samples )
{
if( sampleData == nullptr || samples < 1 )
{
@@ -1182,7 +1182,7 @@ void GigSample::updateSampleRate()
bool GigSample::convertSampleRate( sampleFrame & oldBuf, sampleFrame & newBuf,
bool GigSample::convertSampleRate( SampleFrame & oldBuf, SampleFrame & newBuf,
f_cnt_t oldSize, f_cnt_t newSize, float freq_factor, f_cnt_t& used )
{
if( srcState == nullptr )

View File

@@ -157,7 +157,7 @@ public:
// Needed since libsamplerate stores data internally between calls
void updateSampleRate();
bool convertSampleRate( sampleFrame & oldBuf, sampleFrame & newBuf,
bool convertSampleRate( SampleFrame & oldBuf, SampleFrame & newBuf,
f_cnt_t oldSize, f_cnt_t newSize, float freq_factor, f_cnt_t& used );
gig::Sample * sample;
@@ -243,10 +243,10 @@ public:
GigInstrument( InstrumentTrack * _instrument_track );
~GigInstrument() override;
void play( sampleFrame * _working_buffer ) override;
void play( SampleFrame* _working_buffer ) override;
void playNote( NotePlayHandle * _n,
sampleFrame * _working_buffer ) override;
SampleFrame* _working_buffer ) override;
void deleteNotePluginData( NotePlayHandle * _n ) override;
@@ -312,7 +312,7 @@ private:
Dimension getDimensions( gig::Region * pRegion, int velocity, bool release );
// Load sample data from the Gig file, looping the sample where needed
void loadSample( GigSample& sample, sampleFrame* sampleData, f_cnt_t samples );
void loadSample( GigSample& sample, SampleFrame* sampleData, f_cnt_t samples );
f_cnt_t getLoopedIndex( f_cnt_t index, f_cnt_t startf, f_cnt_t endf ) const;
f_cnt_t getPingPongIndex( f_cnt_t index, f_cnt_t startf, f_cnt_t endf ) const;

View File

@@ -60,7 +60,7 @@ GranularPitchShifterEffect::GranularPitchShifterEffect(Model* parent, const Desc
}
bool GranularPitchShifterEffect::processAudioBuffer(sampleFrame* buf, const fpp_t frames)
bool GranularPitchShifterEffect::processAudioBuffer(SampleFrame* buf, const fpp_t frames)
{
if (!isEnabled() || !isRunning()) { return false; }

View File

@@ -48,7 +48,7 @@ class GranularPitchShifterEffect : public Effect
public:
GranularPitchShifterEffect(Model* parent, const Descriptor::SubPluginFeatures::Key* key);
~GranularPitchShifterEffect() override = default;
bool processAudioBuffer(sampleFrame* buf, const fpp_t frames) override;
bool processAudioBuffer(SampleFrame* buf, const fpp_t frames) override;
EffectControls* controls() override
{

View File

@@ -156,7 +156,7 @@ using DistFX = DspEffectLibrary::Distortion;
using SweepOsc = KickerOsc<DspEffectLibrary::MonoToStereoAdaptor<DistFX>>;
void KickerInstrument::playNote( NotePlayHandle * _n,
sampleFrame * _working_buffer )
SampleFrame* _working_buffer )
{
const fpp_t frames = _n->framesLeftForCurrentPeriod();
const f_cnt_t offset = _n->noteOffset();

View File

@@ -56,7 +56,7 @@ public:
~KickerInstrument() override = default;
void playNote( NotePlayHandle * _n,
sampleFrame * _working_buffer ) override;
SampleFrame* _working_buffer ) override;
void deleteNotePluginData( NotePlayHandle * _n ) override;
void saveSettings(QDomDocument& doc, QDomElement& elem) override;

View File

@@ -60,7 +60,7 @@ public:
virtual ~KickerOsc() = default;
void update( sampleFrame* buf, const fpp_t frames, const float sampleRate )
void update( SampleFrame* buf, const fpp_t frames, const float sampleRate )
{
for( fpp_t frame = 0; frame < frames; ++frame )
{

View File

@@ -101,7 +101,7 @@ void LOMMEffect::changeSampleRate()
}
bool LOMMEffect::processAudioBuffer(sampleFrame* buf, const fpp_t frames)
bool LOMMEffect::processAudioBuffer(SampleFrame* buf, const fpp_t frames)
{
if (!isEnabled() || !isRunning())
{

View File

@@ -45,7 +45,7 @@ class LOMMEffect : public Effect
public:
LOMMEffect(Model* parent, const Descriptor::SubPluginFeatures::Key* key);
~LOMMEffect() override = default;
bool processAudioBuffer(sampleFrame* buf, const fpp_t frames) override;
bool processAudioBuffer(SampleFrame* buf, const fpp_t frames) override;
EffectControls* controls() override
{

View File

@@ -129,7 +129,7 @@ void LadspaEffect::changeSampleRate()
bool LadspaEffect::processAudioBuffer( sampleFrame * _buf,
bool LadspaEffect::processAudioBuffer( SampleFrame* _buf,
const fpp_t _frames )
{
m_pluginMutex.lock();
@@ -140,13 +140,13 @@ bool LadspaEffect::processAudioBuffer( sampleFrame * _buf,
}
int frames = _frames;
sampleFrame * o_buf = nullptr;
QVarLengthArray<sample_t> sBuf(_frames * DEFAULT_CHANNELS);
SampleFrame* o_buf = nullptr;
QVarLengthArray<SampleFrame> sBuf(_frames);
if( m_maxSampleRate < Engine::audioEngine()->outputSampleRate() )
{
o_buf = _buf;
_buf = reinterpret_cast<sampleFrame*>(sBuf.data());
_buf = sBuf.data();
sampleDown( o_buf, _buf, m_maxSampleRate );
frames = _frames * m_maxSampleRate /
Engine::audioEngine()->outputSampleRate();

View File

@@ -47,7 +47,7 @@ public:
const Descriptor::SubPluginFeatures::Key * _key );
~LadspaEffect() override;
bool processAudioBuffer( sampleFrame * _buf,
bool processAudioBuffer( SampleFrame* _buf,
const fpp_t _frames ) override;
void setControl( int _control, LADSPA_Data _data );

View File

@@ -462,7 +462,7 @@ inline float GET_INC(float freq) {
return freq/Engine::audioEngine()->outputSampleRate(); // TODO: Use actual sampling rate.
}
int Lb302Synth::process(sampleFrame *outbuf, const int size)
int Lb302Synth::process(SampleFrame* outbuf, const int size)
{
const float sampleRatio = 44100.f / Engine::audioEngine()->outputSampleRate();
@@ -732,7 +732,7 @@ void Lb302Synth::initSlide()
}
void Lb302Synth::playNote( NotePlayHandle * _n, sampleFrame * _working_buffer )
void Lb302Synth::playNote( NotePlayHandle * _n, SampleFrame* _working_buffer )
{
if( _n->isMasterNote() || ( _n->hasParent() && _n->isReleased() ) )
{
@@ -791,7 +791,7 @@ void Lb302Synth::processNote( NotePlayHandle * _n )
void Lb302Synth::play( sampleFrame * _working_buffer )
void Lb302Synth::play( SampleFrame* _working_buffer )
{
m_notesMutex.lock();
while( ! m_notes.isEmpty() )

View File

@@ -152,9 +152,9 @@ public:
Lb302Synth( InstrumentTrack * _instrument_track );
~Lb302Synth() override;
void play( sampleFrame * _working_buffer ) override;
void play( SampleFrame* _working_buffer ) override;
void playNote( NotePlayHandle * _n,
sampleFrame * _working_buffer ) override;
SampleFrame* _working_buffer ) override;
void deleteNotePluginData( NotePlayHandle * _n ) override;
@@ -246,7 +246,7 @@ private:
void recalcFilter();
int process(sampleFrame *outbuf, const int size);
int process(SampleFrame* outbuf, const int size);
friend class gui::Lb302SynthView;

View File

@@ -68,7 +68,7 @@ Lv2Effect::Lv2Effect(Model* parent, const Descriptor::SubPluginFeatures::Key *ke
bool Lv2Effect::processAudioBuffer(sampleFrame *buf, const fpp_t frames)
bool Lv2Effect::processAudioBuffer(SampleFrame* buf, const fpp_t frames)
{
if (!isEnabled() || !isRunning()) { return false; }
Q_ASSERT(frames <= static_cast<fpp_t>(m_tmpOutputSmps.size()));

View File

@@ -42,7 +42,7 @@ public:
*/
Lv2Effect(Model* parent, const Descriptor::SubPluginFeatures::Key* _key);
bool processAudioBuffer( sampleFrame* buf, const fpp_t frames ) override;
bool processAudioBuffer( SampleFrame* buf, const fpp_t frames ) override;
EffectControls* controls() override { return &m_controls; }
Lv2FxControls* lv2Controls() { return &m_controls; }
@@ -50,7 +50,7 @@ public:
private:
Lv2FxControls m_controls;
std::vector<sampleFrame> m_tmpOutputSmps;
std::vector<SampleFrame> m_tmpOutputSmps;
};

View File

@@ -177,7 +177,7 @@ bool Lv2Instrument::handleMidiEvent(
// not yet working
#ifndef LV2_INSTRUMENT_USE_MIDI
void Lv2Instrument::playNote(NotePlayHandle *nph, sampleFrame *)
void Lv2Instrument::playNote(NotePlayHandle *nph, SampleFrame*)
{
}
#endif
@@ -185,7 +185,7 @@ void Lv2Instrument::playNote(NotePlayHandle *nph, sampleFrame *)
void Lv2Instrument::play(sampleFrame *buf)
void Lv2Instrument::play(SampleFrame* buf)
{
copyModelsFromLmms();

View File

@@ -77,9 +77,9 @@ public:
bool handleMidiEvent(const MidiEvent &event,
const TimePos &time = TimePos(), f_cnt_t offset = 0) override;
#else
void playNote(NotePlayHandle *nph, sampleFrame *) override;
void playNote(NotePlayHandle *nph, SampleFrame*) override;
#endif
void play(sampleFrame *buf) override;
void play(SampleFrame* buf) override;
/*
misc

View File

@@ -110,7 +110,7 @@ MonstroSynth::MonstroSynth( MonstroInstrument * _i, NotePlayHandle * _nph ) :
}
void MonstroSynth::renderOutput( fpp_t _frames, sampleFrame * _buf )
void MonstroSynth::renderOutput( fpp_t _frames, SampleFrame* _buf )
{
float modtmp; // temp variable for freq modulation
// macros for modulating with env/lfos
@@ -1062,7 +1062,7 @@ MonstroInstrument::MonstroInstrument( InstrumentTrack * _instrument_track ) :
void MonstroInstrument::playNote( NotePlayHandle * _n,
sampleFrame * _working_buffer )
SampleFrame* _working_buffer )
{
const fpp_t frames = _n->framesLeftForCurrentPeriod();
const f_cnt_t offset = _n->noteOffset();

View File

@@ -177,7 +177,7 @@ public:
MonstroSynth( MonstroInstrument * _i, NotePlayHandle * _nph );
virtual ~MonstroSynth() = default;
void renderOutput( fpp_t _frames, sampleFrame * _buf );
void renderOutput( fpp_t _frames, SampleFrame* _buf );
private:
@@ -357,7 +357,7 @@ public:
~MonstroInstrument() override = default;
void playNote( NotePlayHandle * _n,
sampleFrame * _working_buffer ) override;
SampleFrame* _working_buffer ) override;
void deleteNotePluginData( NotePlayHandle * _n ) override;
void saveSettings( QDomDocument & _doc,

View File

@@ -58,7 +58,7 @@ MultitapEchoEffect::MultitapEchoEffect( Model* parent, const Descriptor::SubPlug
m_sampleRate( Engine::audioEngine()->outputSampleRate() ),
m_sampleRatio( 1.0f / m_sampleRate )
{
m_work = new sampleFrame[Engine::audioEngine()->framesPerPeriod()];
m_work = new SampleFrame[Engine::audioEngine()->framesPerPeriod()];
m_buffer.reset();
m_stages = static_cast<int>( m_controls.m_stages.value() );
updateFilters( 0, 19 );
@@ -83,7 +83,7 @@ void MultitapEchoEffect::updateFilters( int begin, int end )
}
void MultitapEchoEffect::runFilter( sampleFrame * dst, sampleFrame * src, StereoOnePole & filter, const fpp_t frames )
void MultitapEchoEffect::runFilter( SampleFrame* dst, SampleFrame* src, StereoOnePole & filter, const fpp_t frames )
{
for( int f = 0; f < frames; ++f )
{
@@ -93,7 +93,7 @@ void MultitapEchoEffect::runFilter( sampleFrame * dst, sampleFrame * src, Stereo
}
bool MultitapEchoEffect::processAudioBuffer( sampleFrame * buf, const fpp_t frames )
bool MultitapEchoEffect::processAudioBuffer( SampleFrame* buf, const fpp_t frames )
{
if( !isEnabled() || !isRunning () )
{

Some files were not shown because too many files have changed in this diff Show More