forked from sbooth/SFBAudioEngine
-
Notifications
You must be signed in to change notification settings - Fork 1
/
AudioDecoder.h
203 lines (160 loc) · 8.91 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
/*
* Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Stephen F. Booth <me@sbooth.org>
* All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of Stephen F. Booth nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <CoreFoundation/CoreFoundation.h>
#include <CoreAudio/CoreAudioTypes.h>
#include "InputSource.h"
// ========================================
// Typedefs
// ========================================
class AudioDecoder;
typedef void
(*AudioDecoderCallback)(void *context,
const AudioDecoder *decoder);
struct AudioDecoderCallbackAndContext
{
AudioDecoderCallback mCallback;
void *mContext;
};
// ========================================
// Error Codes
// ========================================
extern const CFStringRef AudioDecoderErrorDomain;
enum {
AudioDecoderFileFormatNotRecognizedError = 0,
AudioDecoderFileFormatNotSupportedError = 1,
AudioDecoderInputOutputError = 2
};
// ========================================
// Abstract superclass for an audio decoder
// An AudioDecoder is responsible for reading audio data in some format and providing
// it in a PCM format that is handled by an AudioConverter
// ========================================
class AudioDecoder
{
friend class AudioPlayer;
friend class BasicAudioPlayer;
public:
// ========================================
// Information on supported file formats
static CFArrayRef CreateSupportedFileExtensions();
static CFArrayRef CreateSupportedMIMETypes();
static bool HandlesFilesWithExtension(CFStringRef extension);
static bool HandlesMIMEType(CFStringRef mimeType);
// ========================================
// Factory methods that return an AudioDecoder for the specified resource, or nullptr on failure
// If specified, the MIME type will take precedence over file extension-based type resolution
static AudioDecoder * CreateDecoderForURL(CFURLRef url, CFErrorRef *error = nullptr);
static AudioDecoder * CreateDecoderForURL(CFURLRef url, CFStringRef mimeType, CFErrorRef *error = nullptr);
// If this returns nullptr the caller is responsible for deleting inputSource
static AudioDecoder * CreateDecoderForInputSource(InputSource *inputSource, CFErrorRef *error = nullptr);
static AudioDecoder * CreateDecoderForInputSource(InputSource *inputSource, CFStringRef mimeType, CFErrorRef *error = nullptr);
// Limit decoding to a specified region
static AudioDecoder * CreateDecoderForURLRegion(CFURLRef url, SInt64 startingFrame, CFErrorRef *error = nullptr);
static AudioDecoder * CreateDecoderForURLRegion(CFURLRef url, SInt64 startingFrame, UInt32 frameCount, CFErrorRef *error = nullptr);
static AudioDecoder * CreateDecoderForURLRegion(CFURLRef url, SInt64 startingFrame, UInt32 frameCount, UInt32 repeatCount, CFErrorRef *error = nullptr);
static AudioDecoder * CreateDecoderForInputSourceRegion(InputSource *inputSource, SInt64 startingFrame, CFErrorRef *error = nullptr);
static AudioDecoder * CreateDecoderForInputSourceRegion(InputSource *inputSource, SInt64 startingFrame, UInt32 frameCount, CFErrorRef *error = nullptr);
static AudioDecoder * CreateDecoderForInputSourceRegion(InputSource *inputSource, SInt64 startingFrame, UInt32 frameCount, UInt32 repeatCount, CFErrorRef *error = nullptr);
static AudioDecoder * CreateDecoderForDecoderRegion(AudioDecoder *decoder, SInt64 startingFrame, CFErrorRef *error = nullptr);
static AudioDecoder * CreateDecoderForDecoderRegion(AudioDecoder *decoder, SInt64 startingFrame, UInt32 frameCount, CFErrorRef *error = nullptr);
static AudioDecoder * CreateDecoderForDecoderRegion(AudioDecoder *decoder, SInt64 startingFrame, UInt32 frameCount, UInt32 repeatCount, CFErrorRef *error = nullptr);
// ========================================
// Flag to specify whether AudioDecoders created with the above methods should be automatically opened (default is false)
static inline bool AutomaticallyOpenDecoders() { return sAutomaticallyOpenDecoders; }
static inline void SetAutomaticallyOpenDecoders(bool flag) { sAutomaticallyOpenDecoders = flag; }
// ========================================
// Destruction
virtual ~AudioDecoder();
// This class is non-copyable
AudioDecoder(const AudioDecoder& rhs) = delete;
AudioDecoder& operator=(const AudioDecoder& rhs) = delete;
// ========================================
// The URL this decoder will process
inline CFURLRef GetURL() const { return mInputSource->GetURL(); }
// ========================================
// The input source feeding the decoder
inline InputSource * GetInputSource() const { return mInputSource; }
// ========================================
// Audio access (must be implemented by subclasses)
virtual bool Open(CFErrorRef *error = nullptr) = 0;
virtual bool Close(CFErrorRef *error = nullptr) = 0;
inline bool IsOpen() const { return mIsOpen; }
// ========================================
// The native format of the source audio
inline AudioStreamBasicDescription GetSourceFormat() const { return mSourceFormat; }
virtual CFStringRef CreateSourceFormatDescription() const;
// ========================================
// The type of PCM data provided by this decoder
inline AudioStreamBasicDescription GetFormat() const { return mFormat; }
CFStringRef CreateFormatDescription() const;
// ========================================
// The layout of the channels this decoder provides
inline AudioChannelLayout * GetChannelLayout() const { return mChannelLayout; }
CFStringRef CreateChannelLayoutDescription() const;
// ========================================
// Attempt to read frameCount frames of audio, returning the actual number of frames read
virtual UInt32 ReadAudio(AudioBufferList *bufferList, UInt32 frameCount) = 0;
// ========================================
// Source audio information
virtual SInt64 GetTotalFrames() const = 0;
virtual SInt64 GetCurrentFrame() const = 0;
inline SInt64 GetFramesRemaining() const { return GetTotalFrames() - GetCurrentFrame(); }
// ========================================
// Seeking support
virtual bool SupportsSeeking() const { return false; }
virtual SInt64 SeekToFrame(SInt64 /*frame*/) { return -1; }
// ========================================
// AudioPlayer callback support
void SetDecodingStartedCallback(AudioDecoderCallback callback, void *context);
void SetDecodingFinishedCallback(AudioDecoderCallback callback, void *context);
void SetRenderingStartedCallback(AudioDecoderCallback callback, void *context);
void SetRenderingFinishedCallback(AudioDecoderCallback callback, void *context);
protected:
InputSource *mInputSource; // The input source feeding the decoder
AudioStreamBasicDescription mFormat; // The type of PCM data provided by this decoder
AudioChannelLayout *mChannelLayout; // The channel layout for the PCM data, or nullptr if unknown/unspecified
AudioStreamBasicDescription mSourceFormat; // The native format of the source file
bool mIsOpen; // Subclasses should set this to true if Open() is successful
// and false if Close() is successful
// ========================================
// For subclass use only
AudioDecoder();
AudioDecoder(InputSource *inputSource);
private:
static bool sAutomaticallyOpenDecoders;
// ========================================
// Callbacks for AudioPlayer use only
AudioDecoderCallbackAndContext mCallbacks [4];
void PerformDecodingStartedCallback();
void PerformDecodingFinishedCallback();
void PerformRenderingStartedCallback();
void PerformRenderingFinishedCallback();
};