FSAudioStream.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
  1. /*
  2. * This file is part of the FreeStreamer project,
  3. * (C)Copyright 2011-2018 Matias Muhonen <mmu@iki.fi> 穆马帝
  4. * See the file ''LICENSE'' for using the code.
  5. *
  6. * https://github.com/muhku/FreeStreamer
  7. */
  8. #import <Foundation/Foundation.h>
  9. #if (defined(TARGET_OS_MACCATALYST) && TARGET_OS_MACCATALYST)
  10. #import <CoreAudioTypes/CoreAudioBaseTypes.h>
  11. #else
  12. #import <CoreAudio/CoreAudioTypes.h>
  13. #endif
  14. /**
  15. * The major version of the current release.
  16. */
  17. #define FREESTREAMER_VERSION_MAJOR 4
  18. /**
  19. * The minor version of the current release.
  20. */
  21. #define FREESTREAMER_VERSION_MINOR 0
  22. /**
  23. * The reversion of the current release
  24. */
  25. #define FREESTREAMER_VERSION_REVISION 1
  26. /**
  27. * Follow this notification for the audio stream state changes.
  28. */
  29. extern NSString* const FSAudioStreamStateChangeNotification;
  30. extern NSString* const FSAudioStreamNotificationKey_State;
  31. /**
  32. * Follow this notification for the audio stream errors.
  33. */
  34. extern NSString* const FSAudioStreamErrorNotification;
  35. extern NSString* const FSAudioStreamNotificationKey_Error;
  36. /**
  37. * Follow this notification for the audio stream metadata.
  38. */
  39. extern NSString* const FSAudioStreamMetaDataNotification;
  40. extern NSString* const FSAudioStreamNotificationKey_MetaData;
  41. /**
  42. * The audio stream state.
  43. */
  44. typedef NS_ENUM(NSInteger, FSAudioStreamState) {
  45. /**
  46. * Retrieving URL.
  47. */
  48. kFsAudioStreamRetrievingURL,
  49. /**
  50. * Stopped.
  51. */
  52. kFsAudioStreamStopped,
  53. /**
  54. * Buffering.
  55. */
  56. kFsAudioStreamBuffering,
  57. /**
  58. * Playing.
  59. */
  60. kFsAudioStreamPlaying,
  61. /**
  62. * Paused.
  63. */
  64. kFsAudioStreamPaused,
  65. /**
  66. * Seeking.
  67. */
  68. kFsAudioStreamSeeking,
  69. /**
  70. * The stream has received all the data for a file.
  71. */
  72. kFSAudioStreamEndOfFile,
  73. /**
  74. * Failed.
  75. */
  76. kFsAudioStreamFailed,
  77. /**
  78. * Started retrying.
  79. */
  80. kFsAudioStreamRetryingStarted,
  81. /**
  82. * Retrying succeeded.
  83. */
  84. kFsAudioStreamRetryingSucceeded,
  85. /**
  86. * Retrying failed.
  87. */
  88. kFsAudioStreamRetryingFailed,
  89. /**
  90. * Playback completed.
  91. */
  92. kFsAudioStreamPlaybackCompleted,
  93. /**
  94. * Unknown state.
  95. */
  96. kFsAudioStreamUnknownState
  97. };
  98. /**
  99. * The audio stream errors.
  100. */
  101. typedef NS_ENUM(NSInteger, FSAudioStreamError) {
  102. /**
  103. * No error.
  104. */
  105. kFsAudioStreamErrorNone = 0,
  106. /**
  107. * Error opening the stream.
  108. */
  109. kFsAudioStreamErrorOpen = 1,
  110. /**
  111. * Error parsing the stream.
  112. */
  113. kFsAudioStreamErrorStreamParse = 2,
  114. /**
  115. * Network error.
  116. */
  117. kFsAudioStreamErrorNetwork = 3,
  118. /**
  119. * Unsupported format.
  120. */
  121. kFsAudioStreamErrorUnsupportedFormat = 4,
  122. /**
  123. * Stream buffered too often.
  124. */
  125. kFsAudioStreamErrorStreamBouncing = 5,
  126. /**
  127. * Stream playback was terminated by the operating system.
  128. */
  129. kFsAudioStreamErrorTerminated = 6
  130. };
  131. @protocol FSPCMAudioStreamDelegate;
  132. @class FSAudioStreamPrivate;
  133. /**
  134. * The audio stream playback position.
  135. */
  136. typedef struct {
  137. unsigned minute;
  138. unsigned second;
  139. /**
  140. * Playback time in seconds.
  141. */
  142. float playbackTimeInSeconds;
  143. /**
  144. * Position within the stream, where 0 is the beginning
  145. * and 1.0 is the end.
  146. */
  147. float position;
  148. } FSStreamPosition;
  149. /**
  150. * The audio stream seek byte offset.
  151. */
  152. typedef struct {
  153. UInt64 start;
  154. UInt64 end;
  155. /**
  156. * Position within the stream, where 0 is the beginning
  157. * and 1.0 is the end.
  158. */
  159. float position;
  160. } FSSeekByteOffset;
  161. /**
  162. * Audio levels.
  163. */
  164. typedef struct {
  165. Float32 averagePower;
  166. Float32 peakPower;
  167. } FSLevelMeterState;
  168. /**
  169. * The low-level stream configuration.
  170. */
  171. @interface FSStreamConfiguration : NSObject {
  172. }
  173. /**
  174. * The number of buffers.
  175. */
  176. @property (nonatomic,assign) unsigned bufferCount;
  177. /**
  178. * The size of each buffer.
  179. */
  180. @property (nonatomic,assign) unsigned bufferSize;
  181. /**
  182. * The number of packet descriptions.
  183. */
  184. @property (nonatomic,assign) unsigned maxPacketDescs;
  185. /**
  186. * The HTTP connection buffer size.
  187. */
  188. @property (nonatomic,assign) unsigned httpConnectionBufferSize;
  189. /**
  190. * The output sample rate.
  191. */
  192. @property (nonatomic,assign) double outputSampleRate;
  193. /**
  194. * The number of output channels.
  195. */
  196. @property (nonatomic,assign) long outputNumChannels;
  197. /**
  198. * The interval within the stream may enter to the buffering state before it fails.
  199. */
  200. @property (nonatomic,assign) int bounceInterval;
  201. /**
  202. * The number of times the stream may enter the buffering state before it fails.
  203. */
  204. @property (nonatomic,assign) int maxBounceCount;
  205. /**
  206. * The stream must start within this seconds before it fails.
  207. */
  208. @property (nonatomic,assign) int startupWatchdogPeriod;
  209. /**
  210. * Allow buffering of this many bytes before the cache is full.
  211. */
  212. @property (nonatomic,assign) int maxPrebufferedByteCount;
  213. /**
  214. * Calculate prebuffer sizes dynamically using the stream bitrate in seconds instead of bytes.
  215. */
  216. @property (nonatomic,assign) BOOL usePrebufferSizeCalculationInSeconds;
  217. /**
  218. * Calculate prebuffer sizes using the packet counts.
  219. */
  220. @property (nonatomic,assign) BOOL usePrebufferSizeCalculationInPackets;
  221. /**
  222. * Require buffering of this many bytes before the playback can start for a continuous stream.
  223. */
  224. @property (nonatomic,assign) float requiredPrebufferSizeInSeconds;
  225. /**
  226. * Require buffering of this many bytes before the playback can start for a continuous stream.
  227. */
  228. @property (nonatomic,assign) int requiredInitialPrebufferedByteCountForContinuousStream;
  229. /**
  230. * Require buffering of this many bytes before the playback can start a non-continuous stream.
  231. */
  232. @property (nonatomic,assign) int requiredInitialPrebufferedByteCountForNonContinuousStream;
  233. /**
  234. * Require buffering of this many packets before the playback can start.
  235. */
  236. @property (nonatomic,assign) int requiredInitialPrebufferedPacketCount;
  237. /**
  238. * The HTTP user agent used for stream operations.
  239. */
  240. @property (nonatomic,strong) NSString *userAgent;
  241. /**
  242. * The directory used for caching the streamed files.
  243. */
  244. @property (nonatomic,strong) NSString *cacheDirectory;
  245. /**
  246. * The HTTP headers that are appended to the request when the streaming starts. Notice
  247. * that the headers override any headers previously set by FreeStreamer.
  248. */
  249. @property (nonatomic,strong) NSDictionary *predefinedHttpHeaderValues;
  250. /**
  251. * The property determining if caching the streams to the disk is enabled.
  252. */
  253. @property (nonatomic,assign) BOOL cacheEnabled;
  254. /**
  255. * The property determining if seeking from the audio packets stored in cache is enabled.
  256. * The benefit is that seeking is faster in the case the audio packets are already cached in memory.
  257. */
  258. @property (nonatomic,assign) BOOL seekingFromCacheEnabled;
  259. /**
  260. * The property determining if FreeStreamer should handle audio session automatically.
  261. * Leave it on if you don't want to handle the audio session by yourself.
  262. */
  263. @property (nonatomic,assign) BOOL automaticAudioSessionHandlingEnabled;
  264. /**
  265. * The property enables time and pitch conversion for the audio queue. Put it on
  266. * if you want to use the play rate setting.
  267. */
  268. @property (nonatomic,assign) BOOL enableTimeAndPitchConversion;
  269. /**
  270. * Requires the content type given by the server to match an audio content type.
  271. */
  272. @property (nonatomic,assign) BOOL requireStrictContentTypeChecking;
  273. /**
  274. * The maximum size of the disk cache in bytes.
  275. */
  276. @property (nonatomic,assign) int maxDiskCacheSize;
  277. @end
  278. /**
  279. * Statistics on the stream state.
  280. */
  281. @interface FSStreamStatistics : NSObject {
  282. }
  283. /**
  284. * Time when the statistics were gathered.
  285. */
  286. @property (nonatomic,strong) NSDate *snapshotTime;
  287. /**
  288. * Time in a pretty format.
  289. */
  290. @property (nonatomic,readonly) NSString *snapshotTimeFormatted;
  291. /**
  292. * Audio stream packet count.
  293. */
  294. @property (nonatomic,assign) NSUInteger audioStreamPacketCount;
  295. /**
  296. * Audio queue used buffers count.
  297. */
  298. @property (nonatomic,assign) NSUInteger audioQueueUsedBufferCount;
  299. /**
  300. * Audio stream PCM packet queue count.
  301. */
  302. @property (nonatomic,assign) NSUInteger audioQueuePCMPacketQueueCount;
  303. @end
  304. NSString* freeStreamerReleaseVersion(void);
  305. /**
  306. * FSAudioStream is a class for streaming audio files from an URL.
  307. * It must be directly fed with an URL, which contains audio. That is,
  308. * playlists or other non-audio formats yield an error.
  309. *
  310. * To start playback, the stream must be either initialized with an URL
  311. * or the playback URL can be set with the url property. The playback
  312. * is started with the play method. It is possible to pause or stop
  313. * the stream with the respective methods.
  314. *
  315. * Non-continuous streams (audio streams with a known duration) can be
  316. * seeked with the seekToPosition method.
  317. *
  318. * Note that FSAudioStream is not designed to be thread-safe! That means
  319. * that using the streamer from multiple threads without syncronization
  320. * could cause problems. It is recommended to keep the streamer in the
  321. * main thread and call the streamer methods only from the main thread
  322. * (consider using performSelectorOnMainThread: if calls from multiple
  323. * threads are needed).
  324. */
  325. @interface FSAudioStream : NSObject {
  326. FSAudioStreamPrivate *_private;
  327. }
  328. /**
  329. * Initializes the audio stream with an URL.
  330. *
  331. * @param url The URL from which the stream data is retrieved.
  332. */
  333. - (id)initWithUrl:(NSURL *)url;
  334. /**
  335. * Initializes the stream with a configuration.
  336. *
  337. * @param configuration The stream configuration.
  338. */
  339. - (id)initWithConfiguration:(FSStreamConfiguration *)configuration;
  340. /**
  341. * Starts preload the stream. If no preload URL is
  342. * defined, an error will occur.
  343. */
  344. - (void)preload;
  345. /**
  346. * Starts playing the stream. If no playback URL is
  347. * defined, an error will occur.
  348. */
  349. - (void)play;
  350. /**
  351. * Starts playing the stream from the given URL.
  352. *
  353. * @param url The URL from which the stream data is retrieved.
  354. */
  355. - (void)playFromURL:(NSURL*)url;
  356. /**
  357. * Starts playing the stream from the given offset.
  358. * The offset can be retrieved from the stream with the
  359. * currentSeekByteOffset property.
  360. *
  361. * @param offset The offset where to start playback from.
  362. */
  363. - (void)playFromOffset:(FSSeekByteOffset)offset;
  364. /**
  365. * Stops the stream playback.
  366. */
  367. - (void)stop;
  368. /**
  369. * If the stream is playing, the stream playback is paused upon calling pause.
  370. * Otherwise (the stream is paused), calling pause will continue the playback.
  371. */
  372. - (void)pause;
  373. /**
  374. * Rewinds the stream. Only possible for continuous streams.
  375. *
  376. * @param seconds Seconds to rewind the stream.
  377. */
  378. - (void)rewind:(unsigned)seconds;
  379. /**
  380. * Seeks the stream to a given position. Requires a non-continuous stream
  381. * (a stream with a known duration).
  382. *
  383. * @param position The stream position to seek to.
  384. */
  385. - (void)seekToPosition:(FSStreamPosition)position;
  386. /**
  387. * Sets the audio stream playback rate from 0.5 to 2.0.
  388. * Value 1.0 means the normal playback rate. Values below
  389. * 1.0 means a slower playback rate than usual and above
  390. * 1.0 a faster playback rate. Notice that using a faster
  391. * playback rate than 1.0 may mean that you have to increase
  392. * the buffer sizes for the stream still to play.
  393. *
  394. * The play rate has only effect if the stream is playing.
  395. *
  396. * @param playRate The playback rate.
  397. */
  398. - (void)setPlayRate:(float)playRate;
  399. /**
  400. * Returns the playback status: YES if the stream is playing, NO otherwise.
  401. */
  402. - (BOOL)isPlaying;
  403. /**
  404. * Cleans all cached data from the persistent storage.
  405. */
  406. - (void)expungeCache;
  407. /**
  408. * The stream URL.
  409. */
  410. @property (nonatomic,assign) NSURL *url;
  411. /**
  412. * Determines if strict content type checking is required. If the audio stream
  413. * cannot determine that the stream is actually an audio stream, the stream
  414. * does not play. Disabling strict content type checking bypasses the
  415. * stream content type checks and tries to play the stream regardless
  416. * of the content type information given by the server.
  417. */
  418. @property (nonatomic,assign) BOOL strictContentTypeChecking;
  419. /**
  420. * Set an output file to store the stream contents to a file.
  421. */
  422. @property (nonatomic,assign) NSURL *outputFile;
  423. /**
  424. * Sets a default content type for the stream. Used if
  425. * the stream content type is not available.
  426. */
  427. @property (nonatomic,assign) NSString *defaultContentType;
  428. /**
  429. * The property has the content type of the stream, for instance audio/mpeg.
  430. */
  431. @property (nonatomic,readonly) NSString *contentType;
  432. /**
  433. * The property has the suggested file extension for the stream based on the stream content type.
  434. */
  435. @property (nonatomic,readonly) NSString *suggestedFileExtension;
  436. /**
  437. * Sets a default content length for the stream. Used if
  438. * the stream content-length is not available.
  439. */
  440. @property (nonatomic, assign) UInt64 defaultContentLength;
  441. /**
  442. * The property has the content length of the stream (in bytes). The length is zero if
  443. * the stream is continuous.
  444. */
  445. @property (nonatomic,readonly) UInt64 contentLength;
  446. /**
  447. * The number of bytes of audio data. Notice that this may differ
  448. * from the number of bytes the server returns for the content length!
  449. * For instance audio file meta data is excluded from the count.
  450. * Effectively you can use this property for seeking calculations.
  451. */
  452. @property (nonatomic,readonly) UInt64 audioDataByteCount;
  453. /**
  454. * This property has the current playback position, if the stream is non-continuous.
  455. * The current playback position cannot be determined for continuous streams.
  456. */
  457. @property (nonatomic,readonly) FSStreamPosition currentTimePlayed;
  458. /**
  459. * This property has the duration of the stream, if the stream is non-continuous.
  460. * Continuous streams do not have a duration.
  461. */
  462. @property (nonatomic,readonly) FSStreamPosition duration;
  463. /**
  464. * This property has the current seek byte offset of the stream, if the stream is non-continuous.
  465. * Continuous streams do not have a seek byte offset.
  466. */
  467. @property (nonatomic,readonly) FSSeekByteOffset currentSeekByteOffset;
  468. /**
  469. * This property has the bit rate of the stream. The bit rate is initially 0,
  470. * before the stream has processed enough packets to calculate the bit rate.
  471. */
  472. @property (nonatomic,readonly) float bitRate;
  473. /**
  474. * The property is true if the stream is continuous (no known duration).
  475. */
  476. @property (nonatomic,readonly) BOOL continuous;
  477. /**
  478. * The property is true if the stream has been cached locally.
  479. */
  480. @property (nonatomic,readonly) BOOL cached;
  481. /**
  482. * This property has the number of bytes buffered for this stream.
  483. */
  484. @property (nonatomic,readonly) size_t prebufferedByteCount;
  485. /**
  486. * This property holds the current playback volume of the stream,
  487. * from 0.0 to 1.0.
  488. *
  489. * Note that the overall volume is still constrained by the volume
  490. * set by the user! So the actual volume cannot be higher
  491. * than the volume currently set by the user. For example, if
  492. * requesting a volume of 0.5, then the volume will be 50%
  493. * lower than the current playback volume set by the user.
  494. */
  495. @property (nonatomic,assign) float volume;
  496. /**
  497. * The current size of the disk cache.
  498. */
  499. @property (nonatomic,readonly) unsigned long long totalCachedObjectsSize;
  500. /**
  501. * The property determines the amount of times the stream has tried to retry the playback
  502. * in case of failure.
  503. */
  504. @property (nonatomic,readonly) NSUInteger retryCount;
  505. /**
  506. * Holds the maximum amount of playback retries that will be
  507. * performed before entering kFsAudioStreamRetryingFailed state.
  508. * Default is 3.
  509. */
  510. @property (nonatomic,assign) NSUInteger maxRetryCount;
  511. /**
  512. * The property determines the current audio levels.
  513. */
  514. @property (nonatomic,readonly) FSLevelMeterState levels;
  515. /**
  516. * This property holds the current statistics for the stream state.
  517. */
  518. @property (nonatomic,readonly) FSStreamStatistics *statistics;
  519. /**
  520. * Called upon completion of the stream. Note that for continuous
  521. * streams this is never called.
  522. */
  523. @property (copy) void (^onCompletion)(void);
  524. /**
  525. * Called upon a state change.
  526. */
  527. @property (copy) void (^onStateChange)(FSAudioStreamState state);
  528. /**
  529. * Called upon a meta data is available.
  530. */
  531. @property (copy) void (^onMetaDataAvailable)(NSDictionary *metadata);
  532. /**
  533. * Called upon a failure.
  534. */
  535. @property (copy) void (^onFailure)(FSAudioStreamError error, NSString *errorDescription);
  536. /**
  537. * The property has the low-level stream configuration.
  538. */
  539. @property (readonly) FSStreamConfiguration *configuration;
  540. /**
  541. * Delegate.
  542. */
  543. @property (nonatomic,unsafe_unretained) IBOutlet id<FSPCMAudioStreamDelegate> delegate;
  544. @end
  545. /**
  546. * To access the PCM audio data, use this delegate.
  547. */
  548. @protocol FSPCMAudioStreamDelegate <NSObject>
  549. @optional
  550. /**
  551. * Called when there are PCM audio samples available. Do not do any blocking operations
  552. * when you receive the data. Instead, copy the data and process it so that the
  553. * main event loop doesn't block. Failing to do so may cause glitches to the audio playback.
  554. *
  555. * Notice that the delegate callback may occur from other than the main thread so make
  556. * sure your delegate code is thread safe.
  557. *
  558. * @param audioStream The audio stream the samples are from.
  559. * @param samples The samples as a buffer list.
  560. * @param frames The number of frames.
  561. * @param description Description of the data provided.
  562. */
  563. - (void)audioStream:(FSAudioStream *)audioStream samplesAvailable:(AudioBufferList *)samples frames:(UInt32)frames description: (AudioStreamPacketDescription)description;
  564. @end