Beatmup
realtime_playback.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 
21 #include "abstract_playback.h"
22 #include "../../debug.h"
23 #include <mutex>
24 #include <malloc.h>
25 
26 namespace Beatmup {
27  namespace Audio {
28 
29  /**
30  Realtime playback base.
31  Manages a circular buffer queue storing a signal sampled from a Source.
32  */
34  protected:
35  /**
36  Specifies how the output audio signal is handled by the audio backend.
37  */
38  enum class OutputMode {
39  PULL, //!< The output is requested by pullOutput(..) called by the audio backend.
40  PUSH, //!< The output is sent to pushOutput(..) called by the rendering thread.
41  };
42  private:
44 
45  sample8** buffers; //!< buffers containing the data to play
47  int
48  fillIndex, //!< points to the buffer currently being filled
49  sendIndex, //!< points to the first buffer ready for playing
50  playIndex; //!< points to the buffer currently being played; updated only in the callback
51 
52  dtime playingBufferOffset; //!< when pulling output, offset in frames with respect to the currently playing buffer
53  dtime skipFrames; //!< when pulling output, number of frames to skip to give some time to the rendering process
54 
55  /*
56  playIndex ----> sendIndex ----> fillIndex
57  | |
58  queue filled
59  sendIndex = fillIndex: can you go faster, eh?
60  fillIndex ~ playIndex: ok, take some rest
61  playIndex = sendIndex: you're too slow for this job! (underrun)
62  */
63 
64 
65  /**
66  * Allocates all the atomic buffers
67  */
69 
70  /*
71  * Deallocates all the atomic buffers
72  */
73  void freeBuffers();
74 
75 
76  protected:
78 
79  msize bufferSize; //!< size of each buffer in bytes
80 
81  /**
82  * Creates an atomic playing buffer
83  * \param mode the playback mode
84  */
85  virtual sample8* createBuffer(const AbstractPlayback::Mode& mode) const;
86 
87  /**
88  * Frees an atomic playing buffer
89  */
90  virtual void freeBuffer(sample8* buffer) const;
91 
92 
93  /**
94  * Pushes some data to the output
95  */
96  virtual void pushBuffer(sample8 *buffer, int bufferIndex) {};
97 
98 
99  public:
100  virtual ~BasicRealtimePlayback();
101 
102  void initialize(Mode mode);
103 
104  bool process(TaskThread& thread);
105 
106 
107  /**
108  * Starts playback.
109  */
110  virtual void start();
111 
112 
113  /**
114  * Stops playback.
115  */
116  virtual void stop() = 0;
117 
118 
119  inline void bufferQueueCallbackFunc() {
120  // a buffer is played, step forward
121  playIndex++;
122  }
123 
124 
125  /**
126  * Called in pulling output mode to send data to output.
127  * \param buffer Pointer to a buffer to put data to
128  * \param numFrames Number of "frames" (samples per single channel) to put to the buffer
129  */
130  void pullBuffer(sample8 *buffer, dtime numFrames);
131  };
132 
133  }
134 }
Abstract audio playback base class.
virtual void pushBuffer(sample8 *buffer, int bufferIndex)
Pushes some data to the output.
void prepareBuffers(const AbstractPlayback::Mode &mode)
Allocates all the atomic buffers.
sample8 ** buffers
buffers containing the data to play
virtual void freeBuffer(sample8 *buffer) const
Frees an atomic playing buffer.
OutputMode
Specifies how the output audio signal is handled by the audio backend.
@ PULL
The output is requested by pullOutput(..) called by the audio backend.
@ PUSH
The output is sent to pushOutput(..) called by the rendering thread.
int playIndex
points to the buffer currently being played; updated only in the callback
virtual sample8 * createBuffer(const AbstractPlayback::Mode &mode) const
Creates an atomic playing buffer.
dtime playingBufferOffset
when pulling output, offset in frames with respect to the currently playing buffer
bool process(TaskThread &thread)
Executes the task on CPU within a given thread.
void pullBuffer(sample8 *buffer, dtime numFrames)
Called in pulling output mode to send data to output.
int sendIndex
points to the first buffer ready for playing
virtual void stop()=0
Stops playback.
int fillIndex
points to the buffer currently being filled
void initialize(Mode mode)
Initializes the playback setting its main parameters.
msize bufferSize
size of each buffer in bytes
dtime skipFrames
when pulling output, number of frames to skip to give some time to the rendering process
virtual void start()
Starts playback.
Thread executing tasks.
Definition: parallelism.h:154
uint32_t msize
memory size
Definition: basic_types.h:30
int dtime
discrete time
Definition: basic_types.h:37