SuperpoweredAdvancedAudioPlayer.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  1. #ifndef Header_SuperpoweredAdvancedAudioPlayer
  2. #define Header_SuperpoweredAdvancedAudioPlayer
  3. struct SuperpoweredAdvancedAudioPlayerInternals;
  4. struct SuperpoweredAdvancedAudioPlayerBase;
  5. typedef struct stemsCompressor {
  6. bool enabled;
  7. float inputGainDb;
  8. float outputGainDb;
  9. float dryWetPercent;
  10. float ratio;
  11. float attackSec;
  12. float releaseSec;
  13. float thresholdDb;
  14. float hpCutoffHz;
  15. } stemsCompressor;
  16. typedef struct stemsLimiter {
  17. bool enabled;
  18. float releaseSec;
  19. float thresholdDb;
  20. float ceilingDb;
  21. } stemsLimiter;
  22. typedef struct stemsInfo {
  23. char *names[4];
  24. char *colors[4];
  25. stemsCompressor compressor;
  26. stemsLimiter limiter;
  27. } stemsInfo;
  28. typedef enum SuperpoweredAdvancedAudioPlayerSyncMode {
  29. SuperpoweredAdvancedAudioPlayerSyncMode_None,
  30. SuperpoweredAdvancedAudioPlayerSyncMode_Tempo,
  31. SuperpoweredAdvancedAudioPlayerSyncMode_TempoAndBeat
  32. } SuperpoweredAdvancedAudioPlayerSyncMode;
  33. typedef enum SuperpoweredAdvancedAudioPlayerJogMode {
  34. SuperpoweredAdvancedAudioPlayerJogMode_Scratch,
  35. SuperpoweredAdvancedAudioPlayerJogMode_PitchBend,
  36. SuperpoweredAdvancedAudioPlayerJogMode_Parameter
  37. } SuperpoweredAdvancedAudioPlayerJogMode;
  38. typedef enum SuperpoweredAdvancedAudioPlayerEvent {
  39. SuperpoweredAdvancedAudioPlayerEvent_LoadSuccess,
  40. SuperpoweredAdvancedAudioPlayerEvent_LoadError,
  41. SuperpoweredAdvancedAudioPlayerEvent_NetworkError,
  42. SuperpoweredAdvancedAudioPlayerEvent_EOF,
  43. SuperpoweredAdvancedAudioPlayerEvent_JogParameter,
  44. SuperpoweredAdvancedAudioPlayerEvent_DurationChanged,
  45. } SuperpoweredAdvancedAudioPlayerEvent;
  46. typedef struct hlsStreamAlternative {
  47. char *uri, *name, *language, *groupid;
  48. int bps;
  49. bool isDefault, isMp4a;
  50. } hlsStreamAlternative;
  51. #define HLS_DOWNLOAD_EVERYTHING 86401
  52. #define HLS_DOWNLOAD_REMAINING 86400
  53. /**
  54. @brief Events happen asynchronously, implement this callback to get notified.
  55. LoadSuccess, LoadError and NetworkError are called from an internal thread of this object.
  56. EOF (end of file) and ScratchControl are called from the (probably real-time) audio processing thread, you shouldn't do any expensive there.
  57. @param clientData Some custom pointer you set when you created a SuperpoweredAdvancedAudioPlayer instance.
  58. @param event What happened (load success, load error, end of file, jog parameter).
  59. @param value A pointer to a stemsInfo structure or NULL for LoadSuccess (you take ownership over the strings). (const char *) for LoadError, pointing to the error message. (double *) for JogParameter in the range of 0.0 to 1.0. (bool *) for EOF, set it to true to pause playback. Don't call this instance's methods from an EOF event callback!
  60. */
  61. typedef void (* SuperpoweredAdvancedAudioPlayerCallback) (void *clientData, SuperpoweredAdvancedAudioPlayerEvent event, void *value);
  62. /**
  63. The maximum playback or scratch speed.
  64. */
  65. #define SUPERPOWEREDADVANCEDAUDIOPLAYER_MAXSPEED 20.0f
  66. /**
  67. @brief High performance advanced audio player with:
  68. - time-stretching and pitch shifting,
  69. - beat and tempo sync,
  70. - scratching,
  71. - tempo bend,
  72. - looping,
  73. - slip mode,
  74. - fast seeking (cached points),
  75. - momentum and jog wheel handling,
  76. - 0 latency, real-time operation,
  77. - low memory usage (5300 kb plus 200 kb for every cached point),
  78. - thread safety (all methods are thread-safe),
  79. - direct iPod music library access.
  80. Can not be used for offline processing. Supported file types:
  81. - Stereo or mono pcm WAV and AIFF (16-bit int, 24-bit int, 32-bit int or 32-bit IEEE float).
  82. - MP3 (all kind).
  83. - AAC-LC in M4A container (iTunes).
  84. - AAC-LC in ADTS container (.aac).
  85. - Apple Lossless (on iOS only).
  86. - Http Live Streaming (HLS): vod/live/event streams, AAC-LC/MP3 in audio files or MPEG-TS files. Support for byte ranges and AES-128 encryption.
  87. @param positionMs The current position. Always accurate, no matter of time-stretching and other transformations. Read only.
  88. @param positionPercent The current position as a percentage (0.0f to 1.0f). Read only.
  89. @param positionSeconds The current position as seconds elapsed. Read only.
  90. @param displayPositionMs Same as positionMs, but positionMs is not updated until seeking to a different position is finished. This is updated immediately after setPosition() or seek() is called. Read only.
  91. @param durationMs The duration of the current track in milliseconds. Equals to UINT_MAX for live streams. Read only.
  92. @param durationSeconds The duration of the current track in seconds. Equals to UINT_MAX for live streams. Read only.
  93. @param waitingForBuffering Indicates if the player waits for audio data to be bufferred. Read only.
  94. @param playing Indicates if the player is playing or paused. Read only.
  95. @param tempo The current tempo. Read only.
  96. @param masterTempo Time-stretching is enabled or not. Read only.
  97. @param pitchShift Note offset from -12 to 12. 0 means no pitch shift. Read only.
  98. @param pitchShiftCents Pitch shift cents, from -1200 (one octave down) to 1200 (one octave up). 0 means no pitch shift. Read only.
  99. @param bpm Must be correct for syncing. There is no auto-bpm detection inside. Read only.
  100. @param currentBpm The actual bpm of the track (as bpm changes with the current tempo). Read only.
  101. @param slip If enabled, scratching or reverse will maintain the playback position as if you had never entered those modes. Read only.
  102. @param scratching The player is in scratching mode or not. Read only.
  103. @param reverse Indicates if the playback goes backwards. Read only.
  104. @param looping Indicates if looping is enabled. Read only.
  105. @param firstBeatMs Tells where the first beat (the beatgrid) begins. Must be correct for syncing. Read only.
  106. @param msElapsedSinceLastBeat How many milliseconds elapsed since the last beat. Read only.
  107. @param beatIndex Which beat has just happened (1 [1.0f-1.999f], 2 [2.0f-2.999f], 3 [3.0f-3.99f], 4 [4.0f-4.99f]). A value of 0 means "don't know". Read only.
  108. @param bufferStartPercent What is buffered from the original source, start point. Will always be 0 for non-network sources (files). Read only.
  109. @param bufferEndPercent What is buffered from the original source, end point. Will always be 1.0f for non-network sources (files). Read only.
  110. @param currentBps The current download speed.
  111. @param syncMode The current sync mode (off, tempo, or tempo and beat).
  112. @param fixDoubleOrHalfBPM If tempo is >1.4f or <0.6f, it will treat the bpm as half or double. Good for certain genres. False by default.
  113. @param waitForNextBeatWithBeatSync Wait for the next beat if beat-syncing is enabled. False by default.
  114. @param dynamicHLSAlternativeSwitching Dynamicly changing the current HLS alternative to match the available network bandwidth. Default is true.
  115. @param reverseToForwardAtLoopStart If looping and playback direction is reverse, reaching the beginning of the loop will change direction to forward. True by default.
  116. @param downloadSecondsAhead The HLS content download strategy: how many seconds ahead of the playback position to download. Default is HLS_DOWNLOAD_REMAINING, meaning it will download everything after the playback position, until the end. HLS_DOWNLOAD_EVERYTHING downloads before the playback position too.
  117. @param maxDownloadAttempts If HLS download fails, how many times to try until sleep. Default: 100. After sleep, NetworkError is called continously.
  118. @param minTimeStretchingTempo Will not time-stretch, just resample below this tempo. Default: 0.501f (recommended value for low CPU on older mobile devices, such as the first iPad). Set this before an open() call.
  119. @param maxTimeStretchingTempo Will not time-stretch, just resample above this tempo. Default: 2.0f (recommended value for low CPU on older mobile devices, such as the first iPad).
  120. */
  121. class SuperpoweredAdvancedAudioPlayer {
  122. public:
  123. // READ ONLY parameters, don't set them directly, use the methods below.
  124. double positionMs;
  125. float positionPercent;
  126. unsigned int positionSeconds;
  127. double displayPositionMs;
  128. unsigned int durationMs;
  129. unsigned int durationSeconds;
  130. bool waitingForBuffering;
  131. bool playing;
  132. double tempo;
  133. bool masterTempo;
  134. int pitchShift;
  135. int pitchShiftCents;
  136. double bpm;
  137. double currentBpm;
  138. bool slip;
  139. bool scratching;
  140. bool reverse;
  141. bool looping;
  142. double firstBeatMs;
  143. double msElapsedSinceLastBeat;
  144. float beatIndex;
  145. float bufferStartPercent;
  146. float bufferEndPercent;
  147. int currentBps;
  148. // READ-WRITE parameters
  149. SuperpoweredAdvancedAudioPlayerSyncMode syncMode;
  150. bool fixDoubleOrHalfBPM;
  151. bool waitForNextBeatWithBeatSync;
  152. bool dynamicHLSAlternativeSwitching;
  153. bool reverseToForwardAtLoopStart;
  154. int downloadSecondsAhead;
  155. int maxDownloadAttempts;
  156. float minTimeStretchingTempo;
  157. float maxTimeStretchingTempo;
  158. /**
  159. @brief Set the folder path for temporary files. Used for HLS only.
  160. Call this first before any player instance is created. It will create a subfolder with the name "SuperpoweredHLS" in this folder.
  161. @param path File system path of the folder.
  162. */
  163. static void setTempFolder(const char *path);
  164. /**
  165. @brief Remove the temp folder. Use this when your program ends.
  166. */
  167. static void clearTempFolder();
  168. /**
  169. @brief Create a player instance with the current sample rate value.
  170. Example: SuperpoweredAdvancedAudioPlayer player = new SuperpoweredAdvancedAudioPlayer(this, playerCallback, 44100, 4);
  171. @param clientData A custom pointer your callback receives.
  172. @param callback Your callback to receive player events.
  173. @param samplerate The current samplerate.
  174. @param cachedPointCount Sets how many positions can be cached in the memory. Jumping to a cached point happens with 0 latency. Loops are automatically cached.
  175. */
  176. SuperpoweredAdvancedAudioPlayer(void *clientData, SuperpoweredAdvancedAudioPlayerCallback callback, unsigned int samplerate, unsigned int cachedPointCount);
  177. ~SuperpoweredAdvancedAudioPlayer();
  178. /**
  179. @brief Opens a new audio file, with playback paused.
  180. Tempo, pitchShift, masterTempo and syncMode are NOT changed if you open a new one.
  181. @param path The full file system path of the audio file.
  182. @param customHTTPHeaders NULL terminated list of custom headers for http communication.
  183. @param stemsIndex The stems track index for Native Instruments Stems format (0 for sum track, 1/2/3/4 for stem tracks).
  184. */
  185. void open(const char *path, char **customHTTPHeaders = 0, int stemsIndex = 0);
  186. /**
  187. @brief Opens a file, with playback paused.
  188. Tempo, pitchShift, masterTempo and syncMode are NOT changed if you open a new one.
  189. @param path The full file system path of the file.
  190. @param offset The byte offset inside the file.
  191. @param length The byte length from the offset.
  192. @param customHTTPHeaders NULL terminated list of custom headers for http communication.
  193. @param stemsIndex The stems track index for Native Instruments Stems format.
  194. */
  195. void open(const char *path, int offset, int length, char **customHTTPHeaders = 0, int stemsIndex = 0);
  196. /**
  197. @brief Starts playback.
  198. @param synchronised Set it to true for a beat-synced or tempo-synced start.
  199. */
  200. void play(bool synchronised);
  201. /**
  202. @brief Pause playback.
  203. There is no need for a "stop" method, this player is very efficient with the battery and has no significant "stand-by" processing.
  204. @param decelerateSeconds Optional momentum. 0 means pause immediately.
  205. @param slipMs Enable slip mode for a specific amount of time, or 0 to not slip.
  206. */
  207. void pause(float decelerateSeconds = 0, unsigned int slipMs = 0);
  208. /**
  209. @brief Toggle play/pause.
  210. */
  211. void togglePlayback();
  212. /**
  213. @brief Simple seeking to a percentage.
  214. */
  215. void seek(double percent);
  216. /**
  217. @brief Precise seeking.
  218. @param ms Position in milliseconds.
  219. @param andStop If true, stops playback.
  220. @param synchronisedStart If andStop is false, a beat-synced start is possible.
  221. */
  222. void setPosition(double ms, bool andStop, bool synchronisedStart);
  223. /**
  224. @brief Cache a position for zero latency seeking. It will cache around +/- 1 second around this point.
  225. @param ms Position in milliseconds.
  226. @param pointID Use this to provide a custom identifier, so you can overwrite the same point later. Use 255 for a point with no identifier.
  227. */
  228. void cachePosition(double ms, unsigned char pointID);
  229. /**
  230. @brief Loop from a start point with some length.
  231. @param startMs Loop from this millisecond.
  232. @param lengthMs Length in millisecond.
  233. @param jumpToStartMs If the playhead is within the loop, jump to startMs or not.
  234. @param pointID Looping caches startMs, so you can specify a pointID too (or set to 255 if you don't care).
  235. @param synchronisedStart Beat-synced start.
  236. */
  237. bool loop(double startMs, double lengthMs, bool jumpToStartMs, unsigned char pointID, bool synchronisedStart);
  238. /**
  239. @brief Loop from a start to an end point.
  240. @param startMs Loop from this millisecond.
  241. @param endMs Loop to this millisecond.
  242. @param jumpToStartMs If the playhead is within the loop, jump to startMs or not.
  243. @param pointID Looping caches startMs, so you can specify a pointID too (or set to 255 if you don't care).
  244. @param synchronisedStart Beat-synced start.
  245. */
  246. bool loopBetween(double startMs, double endMs, bool jumpToStartMs, unsigned char pointID, bool synchronisedStart);
  247. /**
  248. @brief Exits from the current loop.
  249. */
  250. void exitLoop();
  251. /**
  252. @brief Checks if ms fall into the current loop.
  253. @param ms The position to check in milliseconds.
  254. */
  255. bool msInLoop(double ms);
  256. /**
  257. @brief There is no auto-bpm detection inside, you must set the original bpm of the track with this for syncing.
  258. Should be called after a successful open().
  259. @param newBpm The bpm value. A number below 10.0f means "bpm unknown", and sync will not work.
  260. */
  261. void setBpm(double newBpm);
  262. /**
  263. @brief Beat-sync works only if the first beat's position is known. Set it here.
  264. Should be called after a successful open().
  265. */
  266. void setFirstBeatMs(double ms);
  267. /**
  268. @brief Shows you where the closest beat is to a specific position.
  269. @param ms The position in milliseconds.
  270. @param beatIndex Set to 0 if beat index is not important, 1-4 otherwise.
  271. */
  272. double closestBeatMs(double ms, unsigned char beatIndex);
  273. /**
  274. @brief "Virtual jog wheel" or "virtual turntable" handling.
  275. @param ticksPerTurn Sets the sensitivity of the virtual wheel. Use around 2300 for pixel-perfect touchscreen waveform control.
  276. @param mode Jog wheel mode (scratching, pitch bend, or parameter set in the range 0.0 to 1.0).
  277. @param scratchSlipMs Enable slip mode for a specific amount of time for scratching, or 0 to not slip.
  278. */
  279. void jogTouchBegin(int ticksPerTurn, SuperpoweredAdvancedAudioPlayerJogMode mode, unsigned int scratchSlipMs);
  280. /**
  281. @brief A jog wheel should send some "ticks" according to the movement. A waveform's movement in pixels for example.
  282. @param value The cumulated ticks value.
  283. @param bendStretch Use time-stretching for bending or not (false makes it "audible").
  284. @param bendMaxPercent The maximum tempo change for pitch bend, should be between 0.01f and 0.3f (1% and 30%).
  285. @param bendHoldMs How long to maintain the bended state. A value >= 1000 will hold until endContinuousPitchBend is called.
  286. @param parameterMode True: if there was no jogTouchBegin, SuperpoweredAdvancedAudioPlayerJogMode_Parameter applies. False: if there was no jogTouchBegin, SuperpoweredAdvancedAudioPlayerJogMode_PitchBend applies.
  287. */
  288. void jogTick(int value, bool bendStretch, float bendMaxPercent, unsigned int bendHoldMs, bool parameterMode);
  289. /**
  290. @brief Call this when the jog touch ends.
  291. @param decelerate The decelerating rate for momentum. Set to 0.0f for automatic.
  292. @param synchronisedStart Beat-synced start after decelerating.
  293. */
  294. void jogTouchEnd(float decelerate, bool synchronisedStart);
  295. /**
  296. @brief Sets the relative tempo of the playback.
  297. @param tempo 1.0f is "original speed".
  298. @param masterTempo Enable or disable time-stretching.
  299. */
  300. void setTempo(double tempo, bool masterTempo);
  301. /**
  302. @brief Sets the pitch shift value. Needs masterTempo enabled.
  303. @param pitchShift Note offset from -12 to 12. 0 means no pitch shift.
  304. */
  305. void setPitchShift(int pitchShift);
  306. /**
  307. @brief Sets the pitch shift value with greater precision. Calling this method requires magnitudes more CPU than setPitchShift.
  308. @param pitchShiftCents Limited to >= -1200 and <= 1200. 0 means no pitch shift.
  309. */
  310. void setPitchShiftCents(int pitchShiftCents);
  311. /**
  312. @brief Sets playback direction.
  313. @param reverse Playback direction.
  314. @param slipMs Enable slip mode for a specific amount of time, or 0 to not slip.
  315. */
  316. void setReverse(bool reverse, unsigned int slipMs);
  317. /**
  318. @brief Pitch bend (temporary tempo change).
  319. @param maxPercent The maximum tempo change for pitch bend, should be between 0.01f and 0.3f (1% and 30%).
  320. @param bendStretch Use time-stretching for bending or not (false makes it "audible").
  321. @param faster Playback speed change direction.
  322. @param holdMs How long to maintain the bended state. A value >= 1000 will hold until endContinuousPitchBend is called.
  323. */
  324. void pitchBend(float maxPercent, bool bendStretch, bool faster, unsigned int holdMs);
  325. /**
  326. @brief Ends pitch bend.
  327. */
  328. void endContinuousPitchBend();
  329. /**
  330. @brief Call when scratching starts.
  331. @warning This is an advanced method, use it only if you don't want the jogT... methods.
  332. @param slipMs Enable slip mode for a specific amount of time for scratching, or 0 to not slip.
  333. @param stopImmediately Stop now or not.
  334. */
  335. void startScratch(unsigned int slipMs, bool stopImmediately);
  336. /**
  337. @brief Scratch movement.
  338. @warning This is an advanced method, use it only if you don't want the jogT... methods.
  339. @param pitch The current speed.
  340. @param smoothing Should be between 0.05f (max. smoothing) and 1.0f (no smoothing).
  341. */
  342. void scratch(double pitch, float smoothing);
  343. /**
  344. @brief Ends scratching.
  345. @warning This is an advanced method, use it only if you don't want the jogT... methods.
  346. @param returnToStateBeforeScratch Return to the previous playback state (direction, speed) or not.
  347. */
  348. void endScratch(bool returnToStateBeforeScratch);
  349. /**
  350. @brief Returns the last process() numberOfSamples converted to milliseconds.
  351. */
  352. double lastProcessMs();
  353. /**
  354. @brief Sets the sample rate.
  355. @param samplerate 44100, 48000, etc.
  356. */
  357. void setSamplerate(unsigned int samplerate);
  358. /**
  359. @brief Call this on a phone call or other interruption.
  360. Apple's built-in codec may be used in some cases, for example ALAC files.
  361. Call this after a media server reset or audio session interrupt to resume playback.
  362. */
  363. void onMediaserverInterrupt();
  364. /**
  365. @brief Processes the audio.
  366. @return Put something into output or not.
  367. @param buffer 32-bit interleaved stereo input/output buffer. Should be numberOfSamples * 8 + 64 bytes big.
  368. @param bufferAdd If true, the contents of buffer will be preserved and audio will be added to them. If false, buffer is completely overwritten.
  369. @param numberOfSamples The number of samples to provide.
  370. @param volume 0.0f is silence, 1.0f is "original volume". Changes are automatically smoothed between consecutive processes.
  371. @param masterBpm A bpm value to sync with. Use 0.0f for no syncing.
  372. @param masterMsElapsedSinceLastBeat How many milliseconds elapsed since the last beat on the other stuff we are syncing to. Use -1.0 to ignore.
  373. */
  374. bool process(float *buffer, bool bufferAdd, unsigned int numberOfSamples, float volume = 1.0f, double masterBpm = 0.0f, double masterMsElapsedSinceLastBeat = -1.0);
  375. private:
  376. SuperpoweredAdvancedAudioPlayerInternals *internals;
  377. SuperpoweredAdvancedAudioPlayerBase *base;
  378. SuperpoweredAdvancedAudioPlayer(const SuperpoweredAdvancedAudioPlayer&);
  379. SuperpoweredAdvancedAudioPlayer& operator=(const SuperpoweredAdvancedAudioPlayer&);
  380. };
  381. #endif