LMMS
Loading...
Searching...
No Matches
VibratingString.h
Go to the documentation of this file.
1/*
2 * VibratingString.h - model of a vibrating string lifted from pluckedSynth
3 *
4 * Copyright (c) 2006-2007 Danny McRae <khjklujn/at/yahoo/com>
5 *
6 * This file is part of LMMS - https://lmms.io
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public
19 * License along with this program (see COPYING); if not, write to the
20 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301 USA.
22 *
23 */
24
25#ifndef LMMS_VIBRATING_STRING_H
26#define LMMS_VIBRATING_STRING_H
27
28#include <memory>
29#include <cstdlib>
30
31#include "LmmsTypes.h"
32#include "lmms_math.h"
33
34namespace lmms
35{
36
37
39{
40public:
41 VibratingString() = default;
42 VibratingString(float pitch, float pick, float pickup, const float* impulse, int len,
43 sample_rate_t sampleRate, int oversample, float randomize, float stringLoss, float detune, bool state);
44 ~VibratingString() = default;
45
49 VibratingString& operator=(VibratingString&&) noexcept = default;
50
52 {
53 for (int i = 0; i < m_oversample; ++i)
54 {
55 // Output at pickup position
58
59 // Sample traveling into "bridge"
60 sample_t ym0 = toBridgeAccess(m_toBridge.get(), 1);
61 // Sample to "nut"
62 sample_t ypM = fromBridgeAccess(m_fromBridge.get(), m_fromBridge->length - 2);
63
64 // String state update
65
66 // Decrement pointer and then update
68 // Update and then increment pointer
69 toBridgeUpdate(m_toBridge.get(), -ypM);
70 }
71
72 return m_outsamp[m_choice];
73 }
74
75private:
76 struct DelayLine
77 {
78 std::unique_ptr<sample_t[]> data;
79 int length;
82 };
83
84 std::unique_ptr<DelayLine> m_fromBridge;
85 std::unique_ptr<DelayLine> m_toBridge;
90
91 std::unique_ptr<float[]> m_impulse;
93 float m_state;
94
95 std::unique_ptr<sample_t[]> m_outsamp;
96
97 std::unique_ptr<DelayLine> initDelayLine(int len);
98 void resample(const float* src, f_cnt_t srcFrames, f_cnt_t dstFrames);
99
105 void setDelayLine(DelayLine* dl, int pick, const float* values, int len, float scale, bool state)
106 {
107 const auto randAmt = m_randomize / 2.f - m_randomize;
108 if (!state)
109 {
110 for (int i = 0; i < pick; ++i)
111 {
112 dl->data[i] = scale * values[dl->length - i - 1] + fastRandInc(randAmt);
113 }
114 for (int i = pick; i < dl->length; ++i)
115 {
116 dl->data[i] = scale * values[i - pick] + fastRandInc(randAmt);
117 }
118 }
119 else
120 {
121 if (len + pick > dl->length)
122 {
123 for (int i = pick; i < dl->length; ++i)
124 {
125 dl->data[i] = scale * values[i - pick] + fastRandInc(randAmt);
126 }
127 }
128 else
129 {
130 for (int i = 0; i < len; ++i)
131 {
132 dl->data[i+pick] = scale * values[i] + fastRandInc(randAmt);
133 }
134 }
135 }
136 }
137
148 {
149 sample_t* ptr = dl->pointer;
150 *ptr = insamp * m_stringLoss;
151 ++ptr;
152 if (ptr > dl->end)
153 {
154 ptr = dl->data.get();
155 }
156 dl->pointer = ptr;
157 }
158
168 {
169 sample_t* ptr = dl->pointer;
170 --ptr;
171 if (ptr < dl->data.get())
172 {
173 ptr = dl->end;
174 }
175 *ptr = insamp * m_stringLoss;
176 dl->pointer = ptr;
177 }
178
185 {
186 sample_t* outpos = dl->pointer + position;
187 while (outpos < dl->data.get())
188 {
189 outpos += dl->length;
190 }
191 while (outpos > dl->end)
192 {
193 outpos -= dl->length;
194 }
195 return *outpos;
196 }
197
198 /*
199 * Right-going delay line:
200 * -->---->---->---
201 * x=0
202 * (pointer)
203 * Left-going delay line:
204 * --<----<----<---
205 * x=0
206 * (pointer)
207 */
208
217 {
218 return dlAccess(dl, position);
219 }
220
229 {
230 return dlAccess(dl, position);
231 }
232
234 {
235 m_state = (m_state + insamp) * 0.5;
236 return m_state;
237 }
238};
239
240
241} // namespace lmms
242
243#endif // LMMS_VIBRATING_STRING_H
#define noexcept
Definition DistrhoDefines.h:72
void resample(const float *src, f_cnt_t srcFrames, f_cnt_t dstFrames)
Definition VibratingString.cpp:94
void fromBridgeUpdate(DelayLine *dl, sample_t insamp)
Definition VibratingString.h:167
sample_t nextSample()
Definition VibratingString.h:51
std::unique_ptr< DelayLine > initDelayLine(int len)
Definition VibratingString.cpp:71
void setDelayLine(DelayLine *dl, int pick, const float *values, int len, float scale, bool state)
Definition VibratingString.h:105
VibratingString & operator=(const VibratingString &)=delete
std::unique_ptr< sample_t[]> m_outsamp
Definition VibratingString.h:95
VibratingString(VibratingString &&) noexcept=delete
~VibratingString()=default
float m_state
Definition VibratingString.h:93
static sample_t dlAccess(DelayLine *dl, int position)
Definition VibratingString.h:184
sample_t bridgeReflection(sample_t insamp)
Definition VibratingString.h:233
VibratingString(const VibratingString &)=delete
static sample_t fromBridgeAccess(DelayLine *dl, int position)
Definition VibratingString.h:216
float m_stringLoss
Definition VibratingString.h:89
void toBridgeUpdate(DelayLine *dl, sample_t insamp)
Definition VibratingString.h:147
std::unique_ptr< DelayLine > m_fromBridge
Definition VibratingString.h:84
std::unique_ptr< float[]> m_impulse
Definition VibratingString.h:91
int m_pickupLoc
Definition VibratingString.h:86
int m_oversample
Definition VibratingString.h:87
static sample_t toBridgeAccess(DelayLine *dl, int position)
Definition VibratingString.h:228
int m_choice
Definition VibratingString.h:92
float m_randomize
Definition VibratingString.h:88
std::unique_ptr< DelayLine > m_toBridge
Definition VibratingString.h:85
register unsigned i
Definition inflate.c:1575
JSAMPIMAGE data
Definition jpeglib.h:945
Definition AudioAlsa.cpp:35
T fastRandInc(T upper) noexcept
Returns a pseudorandom number within [0, upper] (inclusive upper bound).
Definition lmms_math.h:126
QPoint position(const QDropEvent *de)
position is a backwards-compatible adapter for QDropEvent::position and pos functions.
Definition DeprecationHelper.h:47
std::uint32_t sample_rate_t
Definition LmmsTypes.h:42
float sample_t
Definition LmmsTypes.h:39
std::uint64_t f_cnt_t
Definition LmmsTypes.h:43
Definition VibratingString.h:77
sample_t * pointer
Definition VibratingString.h:80
sample_t * end
Definition VibratingString.h:81
int length
Definition VibratingString.h:79
std::unique_ptr< sample_t[]> data
Definition VibratingString.h:78