Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
folium-app
GitHub Repository: folium-app/Folium
Path: blob/a-new-beginning/Cherry/Core/include/audio/Blip_Synth.h
2 views
1
2
// Blip_Synth and Blip_Wave are waveform transition synthesizers for adding
3
// waveforms to a Blip_Buffer.
4
5
// Blip_Buffer 0.3.4. Copyright (C) 2003-2005 Shay Green. GNU LGPL license.
6
7
#ifndef BLIP_SYNTH_H
8
#define BLIP_SYNTH_H
9
10
#ifndef BLIP_BUFFER_H
11
#include "Blip_Buffer.h"
12
#endif
13
14
// Quality level. Higher levels are slower, and worse in a few cases.
15
// Use blip_good_quality as a starting point.
16
const int blip_low_quality = 1;
17
const int blip_med_quality = 2;
18
const int blip_good_quality = 3;
19
const int blip_high_quality = 4;
20
21
// Blip_Synth is a transition waveform synthesizer which adds band-limited
22
// offsets (transitions) into a Blip_Buffer. For a simpler interface, use
23
// Blip_Wave (below).
24
//
25
// Range specifies the greatest expected offset that will occur. For a
26
// waveform that goes between +amp and -amp, range should be amp * 2 (half
27
// that if it only goes between +amp and 0). When range is large, a higher
28
// accuracy scheme is used; to force this even when range is small, pass
29
// the negative of range (i.e. -range).
30
template<int quality,int range>
31
class Blip_Synth {
32
BOOST_STATIC_ASSERT( 1 <= quality && quality <= 5 );
33
BOOST_STATIC_ASSERT( -32768 <= range && range <= 32767 );
34
enum {
35
abs_range = (range < 0) ? -range : range,
36
fine_mode = (range > 512 || range < 0),
37
width = (quality < 5 ? quality * 4 : Blip_Buffer::widest_impulse_),
38
res = 1 << blip_res_bits_,
39
impulse_size = width / 2 * (fine_mode + 1),
40
base_impulses_size = width / 2 * (res / 2 + 1),
41
fine_bits = (fine_mode ? (abs_range <= 64 ? 2 : abs_range <= 128 ? 3 :
42
abs_range <= 256 ? 4 : abs_range <= 512 ? 5 : abs_range <= 1024 ? 6 :
43
abs_range <= 2048 ? 7 : 8) : 0)
44
};
45
blip_pair_t_ impulses [impulse_size * res * 2 + base_impulses_size];
46
Blip_Impulse_ impulse;
47
void init() { impulse.init( impulses, width, res, fine_bits ); }
48
public:
49
Blip_Synth() { init(); }
50
Blip_Synth( double volume ) { init(); this->volume( volume ); }
51
52
// Configure low-pass filter (see notes.txt). Not optimized for real-time control
53
void treble_eq( const blip_eq_t& eq ) { impulse.treble_eq( eq ); }
54
55
// Set volume of a transition at amplitude 'range' by setting volume_unit
56
// to v / range
57
void volume( double v ) { impulse.volume_unit( v * (1.0 / abs_range) ); }
58
59
// Set base volume unit of transitions, where 1.0 is a full swing between the
60
// positive and negative extremes. Not optimized for real-time control.
61
void volume_unit( double unit ) { impulse.volume_unit( unit ); }
62
63
// Default Blip_Buffer used for output when none is specified for a given call
64
Blip_Buffer* output() const { return impulse.buf; }
65
void output( Blip_Buffer* b ) { impulse.buf = b; }
66
67
// Add an amplitude offset (transition) with a magnitude of delta * volume_unit
68
// into the specified buffer (default buffer if none specified) at the
69
// specified source time. Delta can be positive or negative. To increase
70
// performance by inlining code at the call site, use offset_inline().
71
void offset( blip_time_t, int delta, Blip_Buffer* ) const;
72
73
void offset_resampled( blip_resampled_time_t, int delta, Blip_Buffer* ) const;
74
void offset_resampled( blip_resampled_time_t t, int o ) const {
75
offset_resampled( t, o, impulse.buf );
76
}
77
void offset( blip_time_t t, int delta ) const {
78
offset( t, delta, impulse.buf );
79
}
80
void offset_inline( blip_time_t time, int delta, Blip_Buffer* buf ) const {
81
offset_resampled( time * buf->factor_ + buf->offset_, delta, buf );
82
}
83
void offset_inline( blip_time_t time, int delta ) const {
84
offset_inline( time, delta, impulse.buf );
85
}
86
};
87
88
// Blip_Wave is a synthesizer for adding a *single* waveform to a Blip_Buffer.
89
// A wave is built from a series of delays and new amplitudes. This provides a
90
// simpler interface than Blip_Synth, nothing more.
91
template<int quality,int range>
92
class Blip_Wave {
93
Blip_Synth<quality,range> synth;
94
blip_time_t time_;
95
int last_amp;
96
void init() { time_ = 0; last_amp = 0; }
97
public:
98
// Start wave at time 0 and amplitude 0
99
Blip_Wave() { init(); }
100
Blip_Wave( double volume ) { init(); this->volume( volume ); }
101
102
// See Blip_Synth for description
103
void volume( double v ) { synth.volume( v ); }
104
void volume_unit( double v ) { synth.volume_unit( v ); }
105
void treble_eq( const blip_eq_t& eq){ synth.treble_eq( eq ); }
106
Blip_Buffer* output() const { return synth.output(); }
107
void output( Blip_Buffer* b ) { synth.output( b ); if ( !b ) time_ = last_amp = 0; }
108
109
// Current time in frame
110
blip_time_t time() const { return time_; }
111
void time( blip_time_t t ) { time_ = t; }
112
113
// Current amplitude of wave
114
int amplitude() const { return last_amp; }
115
void amplitude( int );
116
117
// Move forward by 't' time units
118
void delay( blip_time_t t ) { time_ += t; }
119
120
// End time frame of specified duration. Localize time to new frame.
121
// If wave hadn't been run to end of frame, start it at beginning of new frame.
122
void end_frame( blip_time_t duration )
123
{
124
time_ -= duration;
125
if ( time_ < 0 )
126
time_ = 0;
127
}
128
};
129
130
// End of public interface
131
132
template<int quality,int range>
133
void Blip_Wave<quality,range>::amplitude( int amp ) {
134
int delta = amp - last_amp;
135
last_amp = amp;
136
synth.offset_inline( time_, delta );
137
}
138
139
template<int quality,int range>
140
inline void Blip_Synth<quality,range>::offset_resampled( blip_resampled_time_t time,
141
int delta, Blip_Buffer* blip_buf ) const
142
{
143
typedef blip_pair_t_ pair_t;
144
145
unsigned sample_index = (time >> BLIP_BUFFER_ACCURACY) & ~1;
146
assert(( (void)"Blip_Synth/Blip_wave: Went past end of buffer",
147
sample_index < blip_buf->buffer_size_ ));
148
enum { const_offset = Blip_Buffer::widest_impulse_ / 2 - width / 2 };
149
pair_t* buf = (pair_t*) &blip_buf->buffer_ [const_offset + sample_index];
150
151
enum { shift = BLIP_BUFFER_ACCURACY - blip_res_bits_ };
152
enum { mask = res * 2 - 1 };
153
const pair_t* imp = &impulses [((time >> shift) & mask) * impulse_size];
154
155
pair_t offset = impulse.offset * delta;
156
157
if ( !fine_bits )
158
{
159
// normal mode
160
for ( int n = width / 4; n; --n )
161
{
162
pair_t t0 = buf [0] - offset;
163
pair_t t1 = buf [1] - offset;
164
165
t0 += imp [0] * delta;
166
t1 += imp [1] * delta;
167
imp += 2;
168
169
buf [0] = t0;
170
buf [1] = t1;
171
buf += 2;
172
}
173
}
174
else
175
{
176
// fine mode
177
enum { sub_range = 1 << fine_bits };
178
delta += sub_range / 2;
179
int delta2 = (delta & (sub_range - 1)) - sub_range / 2;
180
delta >>= fine_bits;
181
182
for ( int n = width / 4; n; --n )
183
{
184
pair_t t0 = buf [0] - offset;
185
pair_t t1 = buf [1] - offset;
186
187
t0 += imp [0] * delta2;
188
t0 += imp [1] * delta;
189
190
t1 += imp [2] * delta2;
191
t1 += imp [3] * delta;
192
193
imp += 4;
194
195
buf [0] = t0;
196
buf [1] = t1;
197
buf += 2;
198
}
199
}
200
}
201
202
template<int quality,int range>
203
void Blip_Synth<quality,range>::offset( blip_time_t time, int delta, Blip_Buffer* buf ) const {
204
offset_resampled( time * buf->factor_ + buf->offset_, delta, buf );
205
}
206
207
#endif
208
209
210