Beatmup
signal.h
Go to the documentation of this file.
1 /*
2  Beatmup image and signal processing library
3  Copyright (C) 2019, lnstadrum
4 
5  This program is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #pragma once
20 #include "../fragments/sequence.h"
21 #include "../context.h"
22 #include "sample_arithmetic.h"
23 #include "source.h"
24 #include "../utils/input_stream.h"
25 
26 namespace Beatmup {
27 
28 /**
29  Sound I/O and processing API.
30 */
31 namespace Audio {
32 
33  /**
34  An audio signal.
35  */
36  class Signal : public Fragments::SequenceToolkit<Signal> {
37  private:
38  /**
39  Implements a Sequence::Pointer for audio signals
40  */
41  class Pointer : public Sequence::Pointer {
42  public:
43  Pointer(Signal& signal, dtime time, bool writing);
44  virtual void releaseBuffer();
45  unsigned char getChannelCount() const;
46  };
47 
48  public:
49 
50  /**
51  Provides reading access to the signal
52  */
53  class Reader : public Pointer {
54  public:
55  Reader(Signal& signal, dtime time);
56  dtime acquireBuffer(const void* &data);
57  };
58 
59  /**
60  Provides writing access to the signal
61  */
62  class Writer : public Pointer {
63  public:
64  Writer(Signal& signal, dtime time);
65  dtime acquireBuffer(void* &data);
66  };
67 
68  /**
69  Signal dynamics meter
70  */
71  class Meter : public Pointer {
72  public:
73  /**
74  Specifies how to compute signal dynamics (minima and maxima in a given period of time)
75  */
76  enum class MeasuringMode {
77  /**
78  Just run across all samples.
79  This does not require neither precomputing nor extra memory, but slow as hell.
80  */
82 
83  /**
84  Find an approximated range using a lookup tree.
85  It is guaranteed that the resulting approximated dynamic range covers the precise range. Very fast for less
86  fragmented signals, does not hit the sample data in memory, but requires precomputing and increases the
87  memory footprint.
88  */
90 
91  /**
92  Use lookup and then precise the measurement using sample data.
93  Generally fast, except highly fragmented signals. Requires precomputing and increases the memory footprint
94  (same as `approximateUsingLookup`);
95  */
97  };
98 
99  private:
100  /**
101  Measures signal dynamics in a given period of time.
102  Deals with the fragmentation. The sample type must be coherent to the actual sample format of the signal.
103  \param len Period length in samples
104  \param resolution Number of output points
105  \param min Channelwise multiplexed magnitude minima, (resolution) points per channel
106  \param max Channelwise multiplexed magnitude maxima, (resolution) points per channel
107  */
108  template<typename sample> void measureInFragments(dtime len, int resolution, sample* min, sample* max);
109 
110  static void prepare(Signal& signal, int skipOnStart = 0, int numSteps = 1);
111 
113 
114  public:
115  /**
116  Precomputes the dynamics lookup all over the signal, where needed
117  \param signal The signal to process
118  \param runTask If `true`, a task will be run in the context of the signal allowing to process it in parallel;
119  otherwise the computation is done directly in the calling thread
120  */
121  static void prepareSignal(Signal& signal, bool runTask = true);
122 
123  /**
124  Constructs a new meter
125  \param signal The signal to measure
126  \param time Initial time to start measurements from
127  \param mode Algorithm used to measure the signal dynamics
128  */
130 
131  /**
132  Measures signal dynamics in a given period of time.
133  \param len Period length in samples
134  \param resolution Number of output points
135  \param min Channelwise multiplexed magnitude minima, (resolution) points per channel
136  \param max Channelwise multiplexed magnitude maxima, (resolution) points per channel
137  */
138  template<typename sample> void measure(dtime len, int resolution, sample min[], sample max[]);
139 
140  inline void setMode(MeasuringMode newMode) { mode = newMode; }
141  };
142 
143  /**
144  Audio::Source reading samples from a given Signal.
145  */
146  class Source : public Audio::Source {
147  private:
151  unsigned char numChannels;
152 
153  public:
154  Source(Signal&);
155 
156  ThreadIndex getMaxThreads() { return 1; }
157 
158  void prepare(
159  const dtime sampleRate,
161  const unsigned char numChannels,
162  const dtime maxBufferLen
163  );
164 
165  void setClock(dtime time);
166 
167  void render(
168  TaskThread& thread,
169  sample8* buffer,
170  const dtime bufferLength
171  );
172  };
173 
174  /**
175  Communicates an error when inserting a incompatible fragment into a Signal
176  */
177  class IncompatibleFormat : public Exception {
178  public:
181  IncompatibleFormat(const Signal& source, const Signal& dest);
182  };
183 
184  private:
186 
187  AudioSampleFormat format; //!< sample format
188 
190  int sampleRate; //!< sampling frequency
191  unsigned char channelCount; //!< number of channels
192 
193  protected:
194  virtual Signal* createEmpty() const;
195 
196  public:
197  static const int DEFAULT_FRAGMENT_LENGTH_SEC = 5;
198 
199  /**
200  Creates an empty signal
201  \param context A Context instance the new signal is associated to
202  \param format Sample format of the new signal
203  \param sampleRate Sample rate, Hz
204  \param channels Number of channels
205  \param defaultFragmentLenSec Default fragment length in seconds
206  */
207  Signal(Context& context, AudioSampleFormat format, int sampleRate, unsigned char channels, float defaultFragmentLenSec = DEFAULT_FRAGMENT_LENGTH_SEC);
208 
209  /**
210  Inserts a Signal into the current signal at a specific time moment
211  \param signal The signal to insert
212  \param time The time moment to insert the signal at
213  */
214  void insert(const Signal& signal, dtime time);
215 
216  /**
217  Prolongates the sequence if necessary, to ensure given length
218  */
219  void reserve(dtime length);
220 
221  /**
222  Stores the signal to a PCM-encoded WAV file
223  */
224  void saveWAV(const char* filename);
225 
226  static Signal* loadWAV(Context& ctx, const char* fileName);
227  static Signal* loadWAV(Context& ctx, InputStream& inputStream);
228 
229  /**
230  \return number of channels in the signal.
231  */
232  unsigned char getChannelCount() const { return channelCount; }
233 
234  /**
235  \return sample format of the signal.
236  */
238 
239  /**
240  \return a Context instance the signal is attached to.
241  */
242  Context& getContext() const { return ctx; }
243  };
244 
245 }
246 }
Communicates an error when inserting a incompatible fragment into a Signal.
Definition: signal.h:177
IncompatibleFormat(const Signal &source, const Signal &dest)
Definition: signal.cpp:381
Signal dynamics meter.
Definition: signal.h:71
void measureInFragments(dtime len, int resolution, sample *min, sample *max)
Measures signal dynamics in a given period of time.
Definition: signal.cpp:227
static void prepareSignal(Signal &signal, bool runTask=true)
Precomputes the dynamics lookup all over the signal, where needed.
Definition: signal.cpp:202
void measure(dtime len, int resolution, sample min[], sample max[])
Measures signal dynamics in a given period of time.
Meter(Signal &signal, dtime time, MeasuringMode mode=MeasuringMode::approximateUsingLookup)
Constructs a new meter.
Definition: signal.cpp:197
MeasuringMode
Specifies how to compute signal dynamics (minima and maxima in a given period of time)
Definition: signal.h:76
@ approximateUsingLookup
Find an approximated range using a lookup tree.
@ preciseUsingLookupAndSamples
Use lookup and then precise the measurement using sample data.
@ preciseUsingSamples
Just run across all samples.
void setMode(MeasuringMode newMode)
Definition: signal.h:140
static void prepare(Signal &signal, int skipOnStart=0, int numSteps=1)
Definition: signal.cpp:183
Implements a Sequence::Pointer for audio signals.
Definition: signal.h:41
unsigned char getChannelCount() const
Definition: signal.cpp:151
virtual void releaseBuffer()
Definition: signal.cpp:147
Pointer(Signal &signal, dtime time, bool writing)
Definition: signal.cpp:143
Provides reading access to the signal.
Definition: signal.h:53
Reader(Signal &signal, dtime time)
Definition: signal.cpp:156
dtime acquireBuffer(const void *&data)
Definition: signal.cpp:159
Audio::Source reading samples from a given Signal.
Definition: signal.h:146
unsigned char numChannels
Definition: signal.h:151
void prepare(const dtime sampleRate, const AudioSampleFormat sampleFormat, const unsigned char numChannels, const dtime maxBufferLen)
Prepares a source to render audio data.
Definition: signal.cpp:354
AudioSampleFormat sampleFormat
Definition: signal.h:150
void render(TaskThread &thread, sample8 *buffer, const dtime bufferLength)
Renders audio data to the target output buffer given by the user.
Definition: signal.cpp:370
ThreadIndex getMaxThreads()
Returns the maximum number of working threads for rendering from this source.
Definition: signal.h:156
void setClock(dtime time)
Called by the source user when an abrupt time change occurs (e.g., due to seeking)
Definition: signal.cpp:365
Provides writing access to the signal.
Definition: signal.h:62
Writer(Signal &signal, dtime time)
Definition: signal.cpp:170
dtime acquireBuffer(void *&data)
Definition: signal.cpp:172
An audio signal.
Definition: signal.h:36
void insert(const Signal &signal, dtime time)
Inserts a Signal into the current signal at a specific time moment.
Definition: signal.cpp:47
Context & getContext() const
Definition: signal.h:242
unsigned char getChannelCount() const
Definition: signal.h:232
static const int DEFAULT_FRAGMENT_LENGTH_SEC
Definition: signal.h:197
AudioSampleFormat format
sample format
Definition: signal.h:187
AudioSampleFormat getSampleFormat() const
Definition: signal.h:237
Signal(Context &context, AudioSampleFormat format, int sampleRate, unsigned char channels, float defaultFragmentLenSec=DEFAULT_FRAGMENT_LENGTH_SEC)
Creates an empty signal.
Definition: signal.cpp:36
unsigned char channelCount
number of channels
Definition: signal.h:191
void reserve(dtime length)
Prolongates the sequence if necessary, to ensure given length.
Definition: signal.cpp:54
static Signal * loadWAV(Context &ctx, const char *fileName)
Definition: signal.cpp:64
int sampleRate
sampling frequency
Definition: signal.h:190
void saveWAV(const char *filename)
Stores the signal to a PCM-encoded WAV file.
Definition: signal.cpp:117
virtual Signal * createEmpty() const
Initializes an empty sequence, used to bootstrap copying operations.
Definition: signal.cpp:31
const dtime defaultFragmentSize
Definition: signal.h:189
Abstract source of audio signal.
Definition: source.h:30
Basic class: task and memory management, any kind of static data.
Definition: context.h:59
Base class for all exceptions.
Definition: exception.h:37
Minimal input stream interface.
Definition: input_stream.h:27
Thread executing tasks.
Definition: parallelism.h:154
unsigned char ThreadIndex
number of threads / thread index
Definition: parallelism.h:68
int dtime
discrete time
Definition: basic_types.h:37
AudioSampleFormat
Format of audio samples.
CustomPoint< numeric > min(const CustomPoint< numeric > &a, const CustomPoint< numeric > &b)
Definition: geometry.h:724
CustomPoint< numeric > max(const CustomPoint< numeric > &a, const CustomPoint< numeric > &b)
Definition: geometry.h:728
JNIEnv jobject jint jint jint channels
JNIEnv jlong jstring filename
jlong jlong jint time