-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathAudioDecoder.h
204 lines (168 loc) · 5.49 KB
/
AudioDecoder.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
#pragma once
#include "AudioStream.h"
#include "base/CCRef.h"
#include <string>
namespace audio
{
class SoundData;
class Decoder : public cocos2d::Ref
{
public:
enum class DecoderType
{
UNKNOWN,
WAV,
VORBIS,
FLAC,
MP3
};
struct AudioInfo
{
int64_t totalFrames = 0;
int64_t bytesPerFrame = 4;
int64_t sampleRate = 44100;
int64_t channelCount = 2;
bool operator==(const AudioInfo& other) const {
return totalFrames == other.totalFrames&&bytesPerFrame == other.bytesPerFrame&&
sampleRate == other.sampleRate&&channelCount == other.channelCount;
}
bool operator!=(const AudioInfo& other) const {
return !(*this == other);
}
double getTotalTime() const {
return (double)totalFrames / sampleRate;
}
int64_t getBitDepth() const {
return bytesPerFrame / channelCount * 8;
}
std::string toString();
};
protected:
Decoder(size_t bufferSize, DecoderType type);
virtual ~Decoder();
public:
static DecoderType getDecoderTypeFromPath(const std::string& path);
static Decoder* createFromStream(Stream* s, size_t bufferSize, DecoderType type);
static Decoder* createFromFile(const std::string& path, size_t bufferSize, DecoderType type = DecoderType::UNKNOWN);
static Decoder* createFromLocalFile(const std::string& path, size_t bufferSize, DecoderType type = DecoderType::UNKNOWN);
static Decoder* createFromStringData(const std::string& str, size_t bufferSize, DecoderType type);
static Decoder* createFromSoundData(SoundData* soundData, size_t bufferSize, DecoderType type);
/**
* Indicates how many bytes of raw data should be generated at each
* call to Decode.
**/
static constexpr int DEFAULT_BUFFER_SIZE = 16384;
/**
* Indicates the quality of the sound.
**/
static constexpr int DEFAULT_SAMPLE_RATE = 44100;
/**
* Default is stereo.
**/
static constexpr int DEFAULT_CHANNELS = 2;
/**
* 16 bit audio is the default.
**/
static constexpr int DEFAULT_BIT_DEPTH = 16;
/**
* Creates a deep of itself. The sound stream can (and should) be
* rewound, and does not have to be at the same place.
* @return A new Decoder object.
**/
Decoder* clone();
/**
* Decodes the next chunk of the music stream, this will usually be
* bufferSize amount of bytes, unless EOF occurs. Zero or negative values
* indicate EOF or errors.
* @return The number of bytes actually decoded.
**/
virtual int64_t decode();
virtual int64_t decode(char* dst, uint64_t bytesToRead) = 0;
/**
* Gets the size of the buffer (NOT the size of the entire stream).
* @return The size of the buffer.
**/
virtual int getBufferSize() const;
/**
* Gets a pointer to the actual data. The contents of this buffer will
* change with each call to decode, so the client must copy the data.
* @return A buffer to raw sound data.
**/
virtual int8_t* getBuffer() const;
/**
* Seeks to the specified position, if possible.
* @param seconds The position in the stream in seconds.
* @return True if success, false on fail/unsupported.
**/
virtual bool seekTime(double seconds);
/**
* Seeks to the specified position, if possible.
* @param frameOffset The position in the stream in frames.
* @return True if success, false on fail/unsupported.
**/
virtual bool seek(int64_t frameOffset) = 0;
/**
* @brief Tells the current frame offset.
* @return The current frame offset.
*/
virtual int64_t tell() = 0;
/**
* Rewinds the stream to the start.
* @return True if success, false on fail/unsupported.
**/
virtual bool rewind();
/**
* Checks whether a stream is seekable.
* @return True if seekable, false otherwise.
**/
virtual bool isSeekable() = 0;
/**
* Checks whether a stream has more data to decode or not. Use
* rewind to start the stream again.
* @return False if there is more data, true on EOF.
**/
virtual bool isFinished();
/**
* Gets the number of channels in a stream. Supported values are 1 (mono) or 2 (stereo).
* @return Either 1 for mono, 2 for stereo, or 0 on errors.
**/
int64_t getChannelCount() const { return audioInfo.channelCount; }
/**
* Gets the number of bits per sample. Supported values are 8 or 16.
* @return Either 8, 16, or 0 if unsupported.
**/
int64_t getBitDepth() const { return audioInfo.getBitDepth(); }
/**
* Gets the sample rate for the Decoder, that is, samples per second.
* @return The sample rate, eg. 44100.
**/
int64_t getSampleRate() const { return audioInfo.sampleRate; }
/**
* Gets the estimated total duration of the stream. in seconds. May return
* -1 if the duration cannot be determined.
**/
double getDuration() const { return audioInfo.getTotalTime(); }
int64_t getTotalFrames() const { return audioInfo.totalFrames; }
int64_t getBytesPerFrame() const { return audioInfo.bytesPerFrame; }
int64_t getBufferOffset() const { return bufferPosition; }
void setLoopingPoint(double tStart, double tEnd);
double getLoopingStart();
double getLoopingEnd();
protected:
int64_t getLoopStart() const;
int64_t getLoopEnd() const;
DecoderType decoderType;
Stream* stream = nullptr;
// When the decoder decodes data incrementally, it writes
// this many bytes at a time (at most).
int bufferSize;
// Holds internal memory.
int8_t* buffer = nullptr;
int64_t bufferPosition = 0;
// Set this to true when eof has been reached.
bool eof = false;
AudioInfo audioInfo;
uint64_t loopStart = 0;
uint64_t loopEnd = 0;
};
}