FSAudioStream.h
16.9 KB
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
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
/*
* This file is part of the FreeStreamer project,
* (C)Copyright 2011-2018 Matias Muhonen <mmu@iki.fi> 穆马帝
* See the file ''LICENSE'' for using the code.
*
* https://github.com/muhku/FreeStreamer
*/
#import <Foundation/Foundation.h>
#import <CoreAudio/CoreAudioTypes.h>
/**
* The major version of the current release.
*/
#define FREESTREAMER_VERSION_MAJOR 4
/**
* The minor version of the current release.
*/
#define FREESTREAMER_VERSION_MINOR 0
/**
* The reversion of the current release
*/
#define FREESTREAMER_VERSION_REVISION 0
/**
* Follow this notification for the audio stream state changes.
*/
extern NSString* const FSAudioStreamStateChangeNotification;
extern NSString* const FSAudioStreamNotificationKey_State;
/**
* Follow this notification for the audio stream errors.
*/
extern NSString* const FSAudioStreamErrorNotification;
extern NSString* const FSAudioStreamNotificationKey_Error;
/**
* Follow this notification for the audio stream metadata.
*/
extern NSString* const FSAudioStreamMetaDataNotification;
extern NSString* const FSAudioStreamNotificationKey_MetaData;
/**
* The audio stream state.
*/
typedef NS_ENUM(NSInteger, FSAudioStreamState) {
/**
* Retrieving URL.
*/
kFsAudioStreamRetrievingURL,
/**
* Stopped.
*/
kFsAudioStreamStopped,
/**
* Buffering.
*/
kFsAudioStreamBuffering,
/**
* Playing.
*/
kFsAudioStreamPlaying,
/**
* Paused.
*/
kFsAudioStreamPaused,
/**
* Seeking.
*/
kFsAudioStreamSeeking,
/**
* The stream has received all the data for a file.
*/
kFSAudioStreamEndOfFile,
/**
* Failed.
*/
kFsAudioStreamFailed,
/**
* Started retrying.
*/
kFsAudioStreamRetryingStarted,
/**
* Retrying succeeded.
*/
kFsAudioStreamRetryingSucceeded,
/**
* Retrying failed.
*/
kFsAudioStreamRetryingFailed,
/**
* Playback completed.
*/
kFsAudioStreamPlaybackCompleted,
/**
* Unknown state.
*/
kFsAudioStreamUnknownState
};
/**
* The audio stream errors.
*/
typedef NS_ENUM(NSInteger, FSAudioStreamError) {
/**
* No error.
*/
kFsAudioStreamErrorNone = 0,
/**
* Error opening the stream.
*/
kFsAudioStreamErrorOpen = 1,
/**
* Error parsing the stream.
*/
kFsAudioStreamErrorStreamParse = 2,
/**
* Network error.
*/
kFsAudioStreamErrorNetwork = 3,
/**
* Unsupported format.
*/
kFsAudioStreamErrorUnsupportedFormat = 4,
/**
* Stream buffered too often.
*/
kFsAudioStreamErrorStreamBouncing = 5,
/**
* Stream playback was terminated by the operating system.
*/
kFsAudioStreamErrorTerminated = 6
};
@protocol FSPCMAudioStreamDelegate;
@class FSAudioStreamPrivate;
/**
* The audio stream playback position.
*/
typedef struct {
unsigned minute;
unsigned second;
/**
* Playback time in seconds.
*/
float playbackTimeInSeconds;
/**
* Position within the stream, where 0 is the beginning
* and 1.0 is the end.
*/
float position;
} FSStreamPosition;
/**
* The audio stream seek byte offset.
*/
typedef struct {
UInt64 start;
UInt64 end;
/**
* Position within the stream, where 0 is the beginning
* and 1.0 is the end.
*/
float position;
} FSSeekByteOffset;
/**
* Audio levels.
*/
typedef struct {
Float32 averagePower;
Float32 peakPower;
} FSLevelMeterState;
/**
* The low-level stream configuration.
*/
@interface FSStreamConfiguration : NSObject {
}
/**
* The number of buffers.
*/
@property (nonatomic,assign) unsigned bufferCount;
/**
* The size of each buffer.
*/
@property (nonatomic,assign) unsigned bufferSize;
/**
* The number of packet descriptions.
*/
@property (nonatomic,assign) unsigned maxPacketDescs;
/**
* The HTTP connection buffer size.
*/
@property (nonatomic,assign) unsigned httpConnectionBufferSize;
/**
* The output sample rate.
*/
@property (nonatomic,assign) double outputSampleRate;
/**
* The number of output channels.
*/
@property (nonatomic,assign) long outputNumChannels;
/**
* The interval within the stream may enter to the buffering state before it fails.
*/
@property (nonatomic,assign) int bounceInterval;
/**
* The number of times the stream may enter the buffering state before it fails.
*/
@property (nonatomic,assign) int maxBounceCount;
/**
* The stream must start within this seconds before it fails.
*/
@property (nonatomic,assign) int startupWatchdogPeriod;
/**
* Allow buffering of this many bytes before the cache is full.
*/
@property (nonatomic,assign) int maxPrebufferedByteCount;
/**
* Calculate prebuffer sizes dynamically using the stream bitrate in seconds instead of bytes.
*/
@property (nonatomic,assign) BOOL usePrebufferSizeCalculationInSeconds;
/**
* Calculate prebuffer sizes using the packet counts.
*/
@property (nonatomic,assign) BOOL usePrebufferSizeCalculationInPackets;
/**
* Require buffering of this many bytes before the playback can start for a continuous stream.
*/
@property (nonatomic,assign) float requiredPrebufferSizeInSeconds;
/**
* Require buffering of this many bytes before the playback can start for a continuous stream.
*/
@property (nonatomic,assign) int requiredInitialPrebufferedByteCountForContinuousStream;
/**
* Require buffering of this many bytes before the playback can start a non-continuous stream.
*/
@property (nonatomic,assign) int requiredInitialPrebufferedByteCountForNonContinuousStream;
/**
* Require buffering of this many packets before the playback can start.
*/
@property (nonatomic,assign) int requiredInitialPrebufferedPacketCount;
/**
* The HTTP user agent used for stream operations.
*/
@property (nonatomic,strong) NSString *userAgent;
/**
* The directory used for caching the streamed files.
*/
@property (nonatomic,strong) NSString *cacheDirectory;
/**
* The HTTP headers that are appended to the request when the streaming starts. Notice
* that the headers override any headers previously set by FreeStreamer.
*/
@property (nonatomic,strong) NSDictionary *predefinedHttpHeaderValues;
/**
* The property determining if caching the streams to the disk is enabled.
*/
@property (nonatomic,assign) BOOL cacheEnabled;
/**
* The property determining if seeking from the audio packets stored in cache is enabled.
* The benefit is that seeking is faster in the case the audio packets are already cached in memory.
*/
@property (nonatomic,assign) BOOL seekingFromCacheEnabled;
/**
* The property determining if FreeStreamer should handle audio session automatically.
* Leave it on if you don't want to handle the audio session by yourself.
*/
@property (nonatomic,assign) BOOL automaticAudioSessionHandlingEnabled;
/**
* The property enables time and pitch conversion for the audio queue. Put it on
* if you want to use the play rate setting.
*/
@property (nonatomic,assign) BOOL enableTimeAndPitchConversion;
/**
* Requires the content type given by the server to match an audio content type.
*/
@property (nonatomic,assign) BOOL requireStrictContentTypeChecking;
/**
* The maximum size of the disk cache in bytes.
*/
@property (nonatomic,assign) int maxDiskCacheSize;
@end
/**
* Statistics on the stream state.
*/
@interface FSStreamStatistics : NSObject {
}
/**
* Time when the statistics were gathered.
*/
@property (nonatomic,strong) NSDate *snapshotTime;
/**
* Time in a pretty format.
*/
@property (nonatomic,readonly) NSString *snapshotTimeFormatted;
/**
* Audio stream packet count.
*/
@property (nonatomic,assign) NSUInteger audioStreamPacketCount;
/**
* Audio queue used buffers count.
*/
@property (nonatomic,assign) NSUInteger audioQueueUsedBufferCount;
/**
* Audio stream PCM packet queue count.
*/
@property (nonatomic,assign) NSUInteger audioQueuePCMPacketQueueCount;
@end
NSString* freeStreamerReleaseVersion(void);
/**
* FSAudioStream is a class for streaming audio files from an URL.
* It must be directly fed with an URL, which contains audio. That is,
* playlists or other non-audio formats yield an error.
*
* To start playback, the stream must be either initialized with an URL
* or the playback URL can be set with the url property. The playback
* is started with the play method. It is possible to pause or stop
* the stream with the respective methods.
*
* Non-continuous streams (audio streams with a known duration) can be
* seeked with the seekToPosition method.
*
* Note that FSAudioStream is not designed to be thread-safe! That means
* that using the streamer from multiple threads without syncronization
* could cause problems. It is recommended to keep the streamer in the
* main thread and call the streamer methods only from the main thread
* (consider using performSelectorOnMainThread: if calls from multiple
* threads are needed).
*/
@interface FSAudioStream : NSObject {
FSAudioStreamPrivate *_private;
}
/**
* Initializes the audio stream with an URL.
*
* @param url The URL from which the stream data is retrieved.
*/
- (id)initWithUrl:(NSURL *)url;
/**
* Initializes the stream with a configuration.
*
* @param configuration The stream configuration.
*/
- (id)initWithConfiguration:(FSStreamConfiguration *)configuration;
/**
* Starts preload the stream. If no preload URL is
* defined, an error will occur.
*/
- (void)preload;
/**
* Starts playing the stream. If no playback URL is
* defined, an error will occur.
*/
- (void)play;
/**
* Starts playing the stream from the given URL.
*
* @param url The URL from which the stream data is retrieved.
*/
- (void)playFromURL:(NSURL*)url;
/**
* Starts playing the stream from the given offset.
* The offset can be retrieved from the stream with the
* currentSeekByteOffset property.
*
* @param offset The offset where to start playback from.
*/
- (void)playFromOffset:(FSSeekByteOffset)offset;
/**
* Stops the stream playback.
*/
- (void)stop;
/**
* If the stream is playing, the stream playback is paused upon calling pause.
* Otherwise (the stream is paused), calling pause will continue the playback.
*/
- (void)pause;
/**
* Rewinds the stream. Only possible for continuous streams.
*
* @param seconds Seconds to rewind the stream.
*/
- (void)rewind:(unsigned)seconds;
/**
* Seeks the stream to a given position. Requires a non-continuous stream
* (a stream with a known duration).
*
* @param position The stream position to seek to.
*/
- (void)seekToPosition:(FSStreamPosition)position;
/**
* Sets the audio stream playback rate from 0.5 to 2.0.
* Value 1.0 means the normal playback rate. Values below
* 1.0 means a slower playback rate than usual and above
* 1.0 a faster playback rate. Notice that using a faster
* playback rate than 1.0 may mean that you have to increase
* the buffer sizes for the stream still to play.
*
* The play rate has only effect if the stream is playing.
*
* @param playRate The playback rate.
*/
- (void)setPlayRate:(float)playRate;
/**
* Returns the playback status: YES if the stream is playing, NO otherwise.
*/
- (BOOL)isPlaying;
/**
* Cleans all cached data from the persistent storage.
*/
- (void)expungeCache;
/**
* The stream URL.
*/
@property (nonatomic,assign) NSURL *url;
/**
* Determines if strict content type checking is required. If the audio stream
* cannot determine that the stream is actually an audio stream, the stream
* does not play. Disabling strict content type checking bypasses the
* stream content type checks and tries to play the stream regardless
* of the content type information given by the server.
*/
@property (nonatomic,assign) BOOL strictContentTypeChecking;
/**
* Set an output file to store the stream contents to a file.
*/
@property (nonatomic,assign) NSURL *outputFile;
/**
* Sets a default content type for the stream. Used if
* the stream content type is not available.
*/
@property (nonatomic,assign) NSString *defaultContentType;
/**
* The property has the content type of the stream, for instance audio/mpeg.
*/
@property (nonatomic,readonly) NSString *contentType;
/**
* The property has the suggested file extension for the stream based on the stream content type.
*/
@property (nonatomic,readonly) NSString *suggestedFileExtension;
/**
* Sets a default content length for the stream. Used if
* the stream content-length is not available.
*/
@property (nonatomic, assign) UInt64 defaultContentLength;
/**
* The property has the content length of the stream (in bytes). The length is zero if
* the stream is continuous.
*/
@property (nonatomic,readonly) UInt64 contentLength;
/**
* The number of bytes of audio data. Notice that this may differ
* from the number of bytes the server returns for the content length!
* For instance audio file meta data is excluded from the count.
* Effectively you can use this property for seeking calculations.
*/
@property (nonatomic,readonly) UInt64 audioDataByteCount;
/**
* This property has the current playback position, if the stream is non-continuous.
* The current playback position cannot be determined for continuous streams.
*/
@property (nonatomic,readonly) FSStreamPosition currentTimePlayed;
/**
* This property has the duration of the stream, if the stream is non-continuous.
* Continuous streams do not have a duration.
*/
@property (nonatomic,readonly) FSStreamPosition duration;
/**
* This property has the current seek byte offset of the stream, if the stream is non-continuous.
* Continuous streams do not have a seek byte offset.
*/
@property (nonatomic,readonly) FSSeekByteOffset currentSeekByteOffset;
/**
* This property has the bit rate of the stream. The bit rate is initially 0,
* before the stream has processed enough packets to calculate the bit rate.
*/
@property (nonatomic,readonly) float bitRate;
/**
* The property is true if the stream is continuous (no known duration).
*/
@property (nonatomic,readonly) BOOL continuous;
/**
* The property is true if the stream has been cached locally.
*/
@property (nonatomic,readonly) BOOL cached;
/**
* This property has the number of bytes buffered for this stream.
*/
@property (nonatomic,readonly) size_t prebufferedByteCount;
/**
* This property holds the current playback volume of the stream,
* from 0.0 to 1.0.
*
* Note that the overall volume is still constrained by the volume
* set by the user! So the actual volume cannot be higher
* than the volume currently set by the user. For example, if
* requesting a volume of 0.5, then the volume will be 50%
* lower than the current playback volume set by the user.
*/
@property (nonatomic,assign) float volume;
/**
* The current size of the disk cache.
*/
@property (nonatomic,readonly) unsigned long long totalCachedObjectsSize;
/**
* The property determines the amount of times the stream has tried to retry the playback
* in case of failure.
*/
@property (nonatomic,readonly) NSUInteger retryCount;
/**
* Holds the maximum amount of playback retries that will be
* performed before entering kFsAudioStreamRetryingFailed state.
* Default is 3.
*/
@property (nonatomic,assign) NSUInteger maxRetryCount;
/**
* The property determines the current audio levels.
*/
@property (nonatomic,readonly) FSLevelMeterState levels;
/**
* This property holds the current statistics for the stream state.
*/
@property (nonatomic,readonly) FSStreamStatistics *statistics;
/**
* Called upon completion of the stream. Note that for continuous
* streams this is never called.
*/
@property (copy) void (^onCompletion)(void);
/**
* Called upon a state change.
*/
@property (copy) void (^onStateChange)(FSAudioStreamState state);
/**
* Called upon a meta data is available.
*/
@property (copy) void (^onMetaDataAvailable)(NSDictionary *metadata);
/**
* Called upon a failure.
*/
@property (copy) void (^onFailure)(FSAudioStreamError error, NSString *errorDescription);
/**
* The property has the low-level stream configuration.
*/
@property (readonly) FSStreamConfiguration *configuration;
/**
* Delegate.
*/
@property (nonatomic,unsafe_unretained) IBOutlet id<FSPCMAudioStreamDelegate> delegate;
@end
/**
* To access the PCM audio data, use this delegate.
*/
@protocol FSPCMAudioStreamDelegate <NSObject>
@optional
/**
* Called when there are PCM audio samples available. Do not do any blocking operations
* when you receive the data. Instead, copy the data and process it so that the
* main event loop doesn't block. Failing to do so may cause glitches to the audio playback.
*
* Notice that the delegate callback may occur from other than the main thread so make
* sure your delegate code is thread safe.
*
* @param audioStream The audio stream the samples are from.
* @param samples The samples as a buffer list.
* @param frames The number of frames.
* @param description Description of the data provided.
*/
- (void)audioStream:(FSAudioStream *)audioStream samplesAvailable:(AudioBufferList *)samples frames:(UInt32)frames description: (AudioStreamPacketDescription)description;
@end