media_audio.h 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. /*
  2. This file is part of Telegram Desktop,
  3. the official desktop application for the Telegram messaging service.
  4. For license and copyright information please follow this link:
  5. https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
  6. */
  7. #pragma once
  8. #include "ui/effects/animation_value.h"
  9. #include "core/file_location.h"
  10. #include "data/data_audio_msg_id.h"
  11. #include "base/bytes.h"
  12. #include "base/timer.h"
  13. #include <QtCore/QTimer>
  14. namespace Ui {
  15. struct PreparedFileInformation;
  16. } // namespace Ui
  17. namespace Media {
  18. struct ExternalSoundData;
  19. struct ExternalSoundPart;
  20. } // namespace Media
  21. namespace Media {
  22. namespace Streaming {
  23. struct TimePoint;
  24. } // namespace Streaming
  25. } // namespace Media
  26. namespace Webrtc {
  27. struct DeviceResolvedId;
  28. } // namespace Webrtc
  29. namespace Media {
  30. namespace Audio {
  31. class Instance;
  32. // Thread: Main.
  33. void Start(not_null<Instance*> instance);
  34. void Finish(not_null<Instance*> instance);
  35. // Thread: Main. Locks: AudioMutex.
  36. bool IsAttachedToDevice();
  37. // Thread: Any. Must be locked: AudioMutex.
  38. bool AttachToDevice();
  39. // Thread: Any.
  40. void ScheduleDetachFromDeviceSafe();
  41. void ScheduleDetachIfNotUsedSafe();
  42. void StopDetachIfNotUsedSafe();
  43. bool SupportsSpeedControl();
  44. } // namespace Audio
  45. namespace Player {
  46. constexpr auto kDefaultFrequency = 48000; // 48 kHz
  47. constexpr auto kTogetherLimit = 4;
  48. constexpr auto kWaveformSamplesCount = 100;
  49. class Fader;
  50. class Loaders;
  51. [[nodiscard]] rpl::producer<AudioMsgId> Updated();
  52. float64 ComputeVolume(AudioMsgId::Type type);
  53. enum class State {
  54. Stopped = 0x01,
  55. StoppedAtEnd = 0x02,
  56. StoppedAtError = 0x03,
  57. StoppedAtStart = 0x04,
  58. Starting = 0x08,
  59. Playing = 0x10,
  60. Stopping = 0x18,
  61. Pausing = 0x20,
  62. Paused = 0x28,
  63. PausedAtEnd = 0x30,
  64. Resuming = 0x38,
  65. };
  66. inline bool IsStopped(State state) {
  67. return (state == State::Stopped)
  68. || (state == State::StoppedAtEnd)
  69. || (state == State::StoppedAtError)
  70. || (state == State::StoppedAtStart);
  71. }
  72. inline bool IsStoppedOrStopping(State state) {
  73. return IsStopped(state) || (state == State::Stopping);
  74. }
  75. inline bool IsStoppedAtEnd(State state) {
  76. return (state == State::StoppedAtEnd);
  77. }
  78. inline bool IsPaused(State state) {
  79. return (state == State::Paused)
  80. || (state == State::PausedAtEnd);
  81. }
  82. inline bool IsPausedOrPausing(State state) {
  83. return IsPaused(state) || (state == State::Pausing);
  84. }
  85. inline bool IsFading(State state) {
  86. return (state == State::Starting)
  87. || (state == State::Stopping)
  88. || (state == State::Pausing)
  89. || (state == State::Resuming);
  90. }
  91. inline bool IsActive(State state) {
  92. return !IsStopped(state) && !IsPaused(state);
  93. }
  94. inline bool ShowPauseIcon(State state) {
  95. return !IsStoppedOrStopping(state)
  96. && !IsPausedOrPausing(state);
  97. }
  98. struct TrackState {
  99. AudioMsgId id;
  100. State state = State::Stopped;
  101. int64 position = 0;
  102. int64 receivedTill = 0;
  103. int64 length = 0;
  104. int frequency = kDefaultFrequency;
  105. int fileHeaderSize = 0;
  106. bool waitingForData = false;
  107. };
  108. class Mixer final : public QObject {
  109. Q_OBJECT
  110. public:
  111. explicit Mixer(not_null<Audio::Instance*> instance);
  112. void play(
  113. const AudioMsgId &audio,
  114. std::unique_ptr<ExternalSoundData> externalData,
  115. crl::time positionMs);
  116. void pause(const AudioMsgId &audio, bool fast = false);
  117. void resume(const AudioMsgId &audio, bool fast = false);
  118. void stop(const AudioMsgId &audio);
  119. void stop(const AudioMsgId &audio, State state);
  120. // External player audio stream interface.
  121. void feedFromExternal(ExternalSoundPart &&part);
  122. void forceToBufferExternal(const AudioMsgId &audioId);
  123. // Thread: Main. Locks: AudioMutex.
  124. void setSpeedFromExternal(const AudioMsgId &audioId, float64 speed);
  125. Streaming::TimePoint getExternalSyncTimePoint(
  126. const AudioMsgId &audio) const;
  127. crl::time getExternalCorrectedTime(
  128. const AudioMsgId &id,
  129. crl::time frameMs,
  130. crl::time systemMs);
  131. void stopAndClear();
  132. TrackState currentState(AudioMsgId::Type type);
  133. // Thread: Main. Must be locked: AudioMutex.
  134. void prepareToCloseDevice();
  135. // Thread: Main. Must be locked: AudioMutex.
  136. void reattachIfNeeded();
  137. // Thread: Any. Must be locked: AudioMutex.
  138. void reattachTracks();
  139. // Thread: Any.
  140. void setSongVolume(float64 volume);
  141. float64 getSongVolume() const;
  142. void setVideoVolume(float64 volume);
  143. float64 getVideoVolume() const;
  144. void scheduleFaderCallback();
  145. ~Mixer();
  146. private Q_SLOTS:
  147. void onError(const AudioMsgId &audio);
  148. void onStopped(const AudioMsgId &audio);
  149. void onUpdated(const AudioMsgId &audio);
  150. Q_SIGNALS:
  151. void updated(const AudioMsgId &audio);
  152. void stoppedOnError(const AudioMsgId &audio);
  153. void loaderOnStart(const AudioMsgId &audio, qint64 positionMs);
  154. void loaderOnCancel(const AudioMsgId &audio);
  155. void suppressSong();
  156. void unsuppressSong();
  157. void suppressAll(qint64 duration);
  158. private:
  159. class Track {
  160. public:
  161. static constexpr int kBuffersCount = 3;
  162. // Thread: Any. Must be locked: AudioMutex.
  163. void reattach(AudioMsgId::Type type);
  164. // Thread: Main. Must be locked: AudioMutex.
  165. void detach();
  166. void clear();
  167. void started();
  168. bool isStreamCreated() const;
  169. void ensureStreamCreated(AudioMsgId::Type type);
  170. int getNotQueuedBufferIndex();
  171. // Thread: Main. Must be locked: AudioMutex.
  172. void setExternalData(std::unique_ptr<ExternalSoundData> data);
  173. void updateStatePosition();
  174. void updateWithSpeedPosition();
  175. [[nodiscard]] static int64 SpeedIndependentPosition(
  176. int64 position,
  177. float64 speed);
  178. [[nodiscard]] static int64 SpeedDependentPosition(
  179. int64 position,
  180. float64 speed);
  181. ~Track();
  182. TrackState state;
  183. Core::FileLocation file;
  184. QByteArray data;
  185. int format = 0;
  186. bool loading = false;
  187. bool loaded = false;
  188. bool waitingForBuffer = false;
  189. // Speed dependent values.
  190. float64 speed = 1.;
  191. float64 nextSpeed = 1.;
  192. struct WithSpeed {
  193. int64 fineTunedPosition = 0;
  194. int64 position = 0;
  195. int64 length = 0;
  196. int64 bufferedPosition = 0;
  197. int64 bufferedLength = 0;
  198. int64 fadeStartPosition = 0;
  199. int samples[kBuffersCount] = { 0 };
  200. QByteArray buffered[kBuffersCount];
  201. };
  202. WithSpeed withSpeed;
  203. struct Stream {
  204. uint32 source = 0;
  205. uint32 buffers[kBuffersCount] = { 0 };
  206. };
  207. Stream stream;
  208. std::unique_ptr<ExternalSoundData> externalData;
  209. crl::time lastUpdateWhen = 0;
  210. crl::time lastUpdatePosition = 0;
  211. private:
  212. void createStream(AudioMsgId::Type type);
  213. void destroyStream();
  214. void resetStream();
  215. };
  216. bool fadedStop(AudioMsgId::Type type, bool *fadedStart = 0);
  217. void resetFadeStartPosition(AudioMsgId::Type type, int positionInBuffered = -1);
  218. bool checkCurrentALError(AudioMsgId::Type type);
  219. void externalSoundProgress(const AudioMsgId &audio);
  220. // Thread: Any. Must be locked: AudioMutex.
  221. void setStoppedState(Track *current, State state = State::Stopped);
  222. Track *trackForType(AudioMsgId::Type type, int index = -1); // -1 uses currentIndex(type)
  223. const Track *trackForType(AudioMsgId::Type type, int index = -1) const;
  224. int *currentIndex(AudioMsgId::Type type);
  225. const int *currentIndex(AudioMsgId::Type type) const;
  226. const not_null<Audio::Instance*> _instance;
  227. int _audioCurrent = 0;
  228. Track _audioTracks[kTogetherLimit];
  229. int _songCurrent = 0;
  230. Track _songTracks[kTogetherLimit];
  231. Track _videoTrack;
  232. QAtomicInt _volumeVideo;
  233. QAtomicInt _volumeSong;
  234. friend class Fader;
  235. friend class Loaders;
  236. QThread _faderThread, _loaderThread;
  237. Fader *_fader;
  238. Loaders *_loader;
  239. rpl::lifetime _lifetime;
  240. };
  241. Mixer *mixer();
  242. class Fader : public QObject {
  243. Q_OBJECT
  244. public:
  245. Fader(QThread *thread);
  246. void songVolumeChanged();
  247. void videoVolumeChanged();
  248. Q_SIGNALS:
  249. void error(const AudioMsgId &audio);
  250. void playPositionUpdated(const AudioMsgId &audio);
  251. void audioStopped(const AudioMsgId &audio);
  252. void needToPreload(const AudioMsgId &audio);
  253. public Q_SLOTS:
  254. void onInit();
  255. void onTimer();
  256. void onSuppressSong();
  257. void onUnsuppressSong();
  258. void onSuppressAll(qint64 duration);
  259. private:
  260. enum {
  261. EmitError = 0x01,
  262. EmitStopped = 0x02,
  263. EmitPositionUpdated = 0x04,
  264. EmitNeedToPreload = 0x08,
  265. };
  266. int32 updateOnePlayback(Mixer::Track *track, bool &hasPlaying, bool &hasFading, float64 volumeMultiplier, bool volumeChanged);
  267. void setStoppedState(Mixer::Track *track, State state = State::Stopped);
  268. QTimer _timer;
  269. bool _volumeChangedSong = false;
  270. bool _volumeChangedVideo = false;
  271. bool _suppressAll = false;
  272. bool _suppressAllAnim = false;
  273. bool _suppressSong = false;
  274. bool _suppressSongAnim = false;
  275. anim::value _suppressVolumeAll;
  276. anim::value _suppressVolumeSong;
  277. crl::time _suppressAllStart = 0;
  278. crl::time _suppressAllEnd = 0;
  279. crl::time _suppressSongStart = 0;
  280. };
  281. [[nodiscard]] Ui::PreparedFileInformation PrepareForSending(
  282. const QString &fname,
  283. const QByteArray &data);
  284. namespace internal {
  285. // Thread: Any. Must be locked: AudioMutex.
  286. bool CheckAudioDeviceConnected();
  287. // Thread: Main. Locks: AudioMutex.
  288. void DetachFromDevice(not_null<Audio::Instance*> instance);
  289. bool DetachIfDeviceChanged(
  290. not_null<Audio::Instance*> instance,
  291. const Webrtc::DeviceResolvedId &nowDeviceId);
  292. // Thread: Any.
  293. QMutex *audioPlayerMutex();
  294. // Thread: Any.
  295. bool audioCheckError();
  296. } // namespace internal
  297. } // namespace Player
  298. } // namespace Media
  299. VoiceWaveform audioCountWaveform(const Core::FileLocation &file, const QByteArray &data);
  300. namespace Media {
  301. namespace Audio {
  302. TG_FORCE_INLINE uint16 ReadOneSample(uchar data) {
  303. return qAbs((static_cast<int16>(data) - 0x80) * 0x100);
  304. }
  305. TG_FORCE_INLINE uint16 ReadOneSample(int16 data) {
  306. return qAbs(data);
  307. }
  308. template <typename SampleType, typename Callback>
  309. void IterateSamples(bytes::const_span bytes, Callback &&callback) {
  310. auto samplesPointer = reinterpret_cast<const SampleType*>(bytes.data());
  311. auto samplesCount = bytes.size() / sizeof(SampleType);
  312. auto samplesData = gsl::make_span(samplesPointer, samplesCount);
  313. for (auto sampleData : samplesData) {
  314. callback(ReadOneSample(sampleData));
  315. }
  316. }
  317. } // namespace Audio
  318. } // namespace Media