forked from EasyRPG/Player
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathaudio_decoder_base.h
289 lines (254 loc) · 7.42 KB
/
audio_decoder_base.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
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
/*
* This file is part of EasyRPG Player.
*
* EasyRPG Player is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EasyRPG Player is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EasyRPG Player. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef EP_AUDIO_DECODER_BASE_H
#define EP_AUDIO_DECODER_BASE_H
// Headers
#include <cstdio>
#include <cstdint>
#include <string>
#include <vector>
#include <memory>
#include <chrono>
#include "filesystem_stream.h"
/**
* The AudioDecoder class provides an abstraction over the decoding of
* common audio formats.
* This is the base class containing shared logic.
* See AudioDecoder for sample based decoding and AudioDecoderMidi for
* Midi event based decoding.
*/
class AudioDecoderBase {
public:
/**
* Takes a linear volume and converts it to a logarithmic used by
* RPG_RT (Direct Sound).
* Do not use this for Midi, is already logarithmic by design.
*
* @param volume linear volume
* @return logarithmic volume
*/
static float AdjustVolume(float volume);
virtual ~AudioDecoderBase() = default;
/** Sample format */
enum class Format {
S8,
U8,
S16,
U16,
S32,
U32,
F32
};
/**
* Writes 'size' bytes in the specified buffer. The data matches the format
* reported by GetFormat.
* When size is is smaller then the amount of written bytes or an error occurs
* the remaining buffer space is cleared.
*
* @param buffer Output buffer
* @param size Size of the buffer in bytes
* @return Number of bytes written to the buffer or -1 on error
*/
int Decode(uint8_t* buffer, int size);
/**
* Decodes the whole audio sample. The data matches the format reported by
* GetFormat.
*
* @return output buffer
*/
std::vector<uint8_t> DecodeAll();
/**
* Rewinds the audio stream to the beginning.
*/
void Rewind();
/**
* Gets if the audio stream will loop when the stream finishes.
*
* @return if looping
*/
virtual bool GetLooping() const;
/**
* Enables/Disables audio stream looping.
* When looping is enabled IsFinished will never return true and the stream
* auto-rewinds (assuming Rewind is supported)
*
* @param enable Enable/Disable looping
*/
virtual void SetLooping(bool enable);
/**
* Gets the number of loops
*
* @return loop count
*/
virtual int GetLoopCount() const;
// Functions to be implemented by the audio decoder
/**
* Assigns a stream to the audio decoder.
* Open should be only called once per audio decoder instance.
* Use GetError to get the error reason on failure.
*
* @return true if initializing was successful, false otherwise
*/
virtual bool Open(Filesystem_Stream::InputStream stream) = 0;
/**
* Pauses the audio decoding.
*/
virtual void Pause() = 0;
/**
* Resumes the audio decoding.
*/
virtual void Resume() = 0;
/**
* Gets the current volume of the audio decoder.
* Fades are considered.
*
* @return current volume (from 0 - 100)
*/
virtual int GetVolume() const = 0;
/**
* Sets the current volume of the audio decoder.
*
* @param volume (from 0-100)
*/
virtual void SetVolume(int volume) = 0;
/**
* Prepares a volume fade in/out effect.
* To do a fade out begin must be larger then end.
* Call Update to do the fade.
*
* @param end End volume (from 0-100)
* @param duration Fade duration in ms
*/
virtual void SetFade(int end, std::chrono::milliseconds duration) = 0;
/**
* Seeks in the audio stream. The value of offset is implementation
* defined but is guaranteed to match the result of Tell.
* Libraries must support at least seek from the start for Rewind().
*
* @param offset Offset to seek to
* @param origin Position to seek from
* @return Whether seek was successful
*/
virtual bool Seek(std::streamoff offset, std::ios_base::seekdir origin) = 0;
/**
* Determines whether the stream is finished.
*
* @return true stream ended
*/
virtual bool IsFinished() const = 0;
/**
* Updates the volume for the fade in/out effect.
*
* @param delta Time in us since the last call of this function.
*/
virtual void Update(std::chrono::microseconds delta) = 0;
/**
* Updates Midi output. Only used by Midi out devices.
* For Midi out devices this must be called at least once per ms.
*
* @param delta Time in us since the last call of this function.
*/
virtual void UpdateMidi(std::chrono::microseconds delta);
/**
* Retrieves the format of the audio decoder.
* It is guaranteed that these settings will stay constant the whole time.
*
* @param frequency Filled with the audio frequency
* @param format Filled with the audio format
* @param channels Filled with the amount of channels
*/
virtual void GetFormat(int& frequency, Format& format, int& channels) const = 0;
/**
* Requests a preferred format from the audio decoder. Not all decoders
* support everything and it's recommended to use the audio hardware
* for audio processing.
* When false is returned use GetFormat to get the real format of the
* output data.
*
* @param frequency Audio frequency
* @param format Audio format
* @param channels Number of channels
* @return true when all settings were set, otherwise false (use GetFormat)
*/
virtual bool SetFormat(int frequency, Format format, int channels);
/**
* Gets the pitch multiplier.
*
* @return pitch multiplier
*/
virtual int GetPitch() const;
/**
* Sets the pitch multiplier.
* 100 = normal speed
* 200 = double speed and so on
* When not supported a resampler will handle the pitch shift.
*
* @param pitch Pitch multiplier to use
* @return true if pitch was set, false otherwise
*/
virtual bool SetPitch(int pitch);
/**
* Tells the current stream position. The value is implementation
* defined.
*
* @return Position in the stream
*/
virtual std::streampos Tell() const;
/**
* Returns a value suitable for the GetMidiTicks command.
* For MIDI this is the amount of MIDI ticks, for other
* formats usually the playback position in seconds.
*
* @return Amount of MIDI ticks or position in seconds
*/
virtual int GetTicks() const = 0;
/**
* Gets the status of the newly created audio decoder.
* Used to make sure the underlying library is properly initialized.
*
* @return true if initializing was succesful, false otherwise
*/
virtual bool WasInited() const;
/**
* Provides an error message when Open or a Decode function fail.
*
* @return Human readable error message
*/
virtual std::string GetError() const;
/**
* Returns the name of the format the current audio decoder decodes in
* lower case.
*
* @return Format name
*/
virtual std::string GetType() const;
protected:
/**
* Called by the Decode functions to fill the buffer.
*
* @param buffer Buffer to fill
* @param size Buffer size
* @return number of bytes read or -1 on error
*/
virtual int FillBuffer(uint8_t* buffer, int size) = 0;
std::string error_message;
std::string music_type;
bool looping = false;
int loop_count = 0;
int Decode(uint8_t* buffer, int length, int recursion_depth);
};
#endif