-
Notifications
You must be signed in to change notification settings - Fork 28
/
StreamRecording.h
191 lines (159 loc) · 6.21 KB
/
StreamRecording.h
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
#ifndef RECORDING_STREAM_H
#define RECORDING_STREAM_H
#include "ManagedBuffer.h"
#include "DataStream.h"
// Pretty much the largest sensible number we can have on a Micro:bit v2
#ifndef CODAL_DEFAULT_STREAM_RECORDING_MAX_LENGTH
#define CODAL_DEFAULT_STREAM_RECORDING_MAX_LENGTH 50000 // 50k, in bytes
#endif
#define REC_STATE_STOPPED 0
#define REC_STATE_PLAYING 1
#define REC_STATE_RECORDING 2
namespace codal
{
class StreamRecording_Buffer {
public:
ManagedBuffer buffer;
StreamRecording_Buffer * next;
StreamRecording_Buffer( ManagedBuffer data ) {
this->buffer = data;
this->next = NULL;
}
};
class StreamRecording : public DataSource, public DataSink
{
private:
//ManagedBuffer buffer[REC_MAX_BUFFERS];
//StreamRecording_Buffer_t * bufferChain;
StreamRecording_Buffer * lastBuffer;
StreamRecording_Buffer * readHead;
uint32_t maxBufferLenth;
uint32_t totalBufferLength;
int state;
float lastUpstreamRate;
DataSink *downStream;
DataSource &upStream;
public:
StreamRecording_Buffer * bufferChain;
/**
* @brief Construct a new Stream Recording object
*
* @param source An upstream DataSource to connect to
* @param length The maximum amount of memory (RAM) in bytes to allow this recording object to use. Defaults to CODAL_DEFAULT_STREAM_RECORDING_MAX_LENGTH.
*/
StreamRecording( DataSource &source, uint32_t length = CODAL_DEFAULT_STREAM_RECORDING_MAX_LENGTH );
/**
* @brief Destroy the Stream Recording object
*/
~StreamRecording();
virtual ManagedBuffer pull();
virtual int pullRequest();
virtual void connect( DataSink &sink );
bool isConnected();
virtual void disconnect();
virtual int getFormat();
virtual int setFormat( int format );
void printChain();
/**
* @brief Calculate and return the length <b>in bytes</b> that this StreamRecording represents
*
* @return int The length, in bytes.
*/
int length();
/**
* @brief Calculate the recorded duration for this StreamRecording.
*
* As this cannot be known by this class (as the sample rate may change during playback <i>or</i> recording) the expected rate must be supplied.
*
* @param sampleRate The sample rate to calculate the duration for, in samples per second.
* @return long The total duration of this StreamRecording, based on the supplied sample rate, in seconds.
*/
float duration( unsigned int sampleRate );
/**
* @brief Downstream classes should use this to determing if there is data to pull from this StreamRecording object.
*
* @return true If data is available
* @return false If the object is completely empty
*/
bool canPull();
/**
* @brief Checks if this object can store any further ManagedBuffers from the upstream components.
*
* @note This does <b>not</b> mean that RAM is completely full, but simply that there is now more internal storage for ManagedBuffer references.
*
* @return true If there are no more slots available to track more ManagedBuffers.
* @return false If there is remaining internal storage capacity for more data
*/
bool isFull();
/**
* @brief Begin recording data from the connected upstream
*
* The StreamRecording object will, if already playing; stop playback, erase its buffer, and start recording.
*
* Non-blocking, will return immediately.
*
* @return Returns true if the object state actually changed (ie. we weren't already recording)
*/
bool recordAsync();
/**
* @brief Begin recording data from the connected upstream
*
* The StreamRecording object will, if already playing; stop playback, erase its buffer, and start recording.
*
* Blocking call, will repeatedly deschedule the current fiber until the recording completes.
*/
void record();
/**
* @brief Begin playing data from the connected upstream
*
* The StreamRecording object will, if already recording; stop recording, rewind to the start of its buffer, and start playing.
*
* Non-blocking, will return immediately.
*
* @return Returns true if the object state actually changed (ie. we weren't already recording)
*/
bool playAsync();
/**
* @brief Begin playing data from the connected upstream
*
* The StreamRecording object will, if already recording; stop recording, rewind to the start of its buffer, and start playing.
*
* Blocking call, will repeatedly deschedule the current fiber until the playback completes.
*/
void play();
/**
* @brief Stop recording or playing the data stored in this StreamRecording object.
*
* Repeated calls to this will do nothing if the object is not in a recording or playback state.
*
* @return Do not use this value, return semantics are changing.
*/
bool stop();
/**
* @brief Erase the internal buffer.
*
* Will also stop playback or recording, if either are active.
*/
void erase();
/**
* @brief Checks if the object is playing back recorded data.
*
* @return True if playing back, else false if stopped or recording.
*/
bool isPlaying();
/**
* @brief Checks if the object is recording new data.
*
* @return True if recording, else false if stopped or playing back.
*/
bool isRecording();
/**
* @brief Checks if the object is stopped
*
* @return True if stopped, else false if recording or playing back.
*/
bool isStopped();
virtual float getSampleRate();
};
}
#endif