File: RingBuffer.h

package info (click to toggle)
lmms 1.2.2%2Bdfsg1-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 55,144 kB
  • sloc: cpp: 159,861; ansic: 98,570; python: 2,555; sh: 551; makefile: 27; xml: 18
file content (217 lines) | stat: -rw-r--r-- 8,921 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
/*
 * RingBuffer.h - an effective and flexible implementation of a ringbuffer for LMMS
 *
 * Copyright (c) 2014 Vesa Kivimäki
 * Copyright (c) 2005-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 RINGBUFFER_H
#define RINGBUFFER_H

#include <QObject>
#include "lmms_basics.h"
#include "lmms_math.h"
#include "MemoryManager.h"

class EXPORT RingBuffer : public QObject
{
	Q_OBJECT
	MM_OPERATORS
public:
/** \brief Constructs a ringbuffer of specified size, will not care about samplerate changes
 * 	\param size The size of the buffer in frames. The actual size will be size + period size
 */
	RingBuffer( f_cnt_t size );

/** \brief Constructs a ringbuffer of specified samplerate-dependent size, which will be updated when samplerate changes
 * 	\param size The size of the buffer in milliseconds. The actual size will be size + period size
 */
	RingBuffer( float size );
	virtual ~RingBuffer();




////////////////////////////////////
//       Provided functions       //
////////////////////////////////////

// utility functions

/** \brief Clears the ringbuffer of any data and resets the position to 0
 */
	void reset();

/** \brief Changes the size of the ringbuffer. Clears all data.
 * 	\param size New size in frames
 */
	void changeSize( f_cnt_t size );

/** \brief Changes the size of the ringbuffer. Clears all data.
 * 	\param size New size in milliseconds
 */
	void changeSize( float size );

/** \brief Sets whether the ringbuffer size is adjusted for samplerate when samplerate changes
 *	\param b True if samplerate should affect buffer size
 */
	void setSamplerateAware( bool b );


// position adjustment functions

/** \brief Advances the position by one period
 */
	void advance();

/** \brief Moves position forwards/backwards by an amount of frames
 * 	\param amount Number of frames to move, may be negative
 */
	void movePosition( f_cnt_t amount );

/** \brief Moves position forwards/backwards by an amount of milliseconds
 * 	\param amount Number of milliseconds to move, may be negative
 */
	void movePosition( float amount );


// read functions

/** \brief Destructively reads a period-sized buffer from the current position, writes it
 * 	to a specified destination, and advances the position by one period
 * 	\param dst Destination pointer
 */
	void pop( sampleFrame * dst );

// note: ringbuffer position is unaffected by all other read functions beside pop()

/** \brief Reads a period-sized buffer 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
 */
	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 );

/** \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 );

/** \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 );


// write functions

/** \brief Writes a buffer of sampleframes 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 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 );

/** \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 );

/** \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 );

/** \brief Mixes a buffer of sampleframes additively to the ringbuffer at specified position, with
 * 	a specified multiplier applied to the frames
 * 	\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!
 * 	\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 );

/** \brief Mixes a buffer of sampleframes additively to the ringbuffer at specified position, with
 * 	a specified multiplier applied to the frames
 * 	\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
 * 	\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 );

/** \brief Mixes a buffer of sampleframes additively to the ringbuffer at specified position, with
 * 	a specified multiplier applied to the frames, with swapped channels
 * 	\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!
 * 	\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 );

/** \brief Mixes a buffer of sampleframes additively to the ringbuffer at specified position, with
 * 	a specified multiplier applied to the frames, with swapped channels
 * 	\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
 * 	\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 );


protected slots:
	void updateSamplerate();

private:
	inline f_cnt_t msToFrames( float ms )
	{
		return static_cast<f_cnt_t>( ceilf( ms * (float)m_samplerate * 0.001f ) );
	}

	const fpp_t m_fpp;
	sample_rate_t m_samplerate;
	size_t m_size;
	sampleFrame * m_buffer;
	volatile unsigned int m_position;

};
#endif