AudioPlayer.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. #include "AudioPlayer.h"
  2. #include <cstring>
  3. #include <cmath>
  4. #include <QDebug>
  5. extern "C" {
  6. #include <libavutil/avutil.h>
  7. #include <libavutil/samplefmt.h>
  8. #include <libavutil/channel_layout.h>
  9. #include <libavutil/frame.h>
  10. #include <libavutil/mem.h>
  11. #include <libswresample/swresample.h>
  12. }
  13. #include "sonic/sonic.h"
  14. AudioPlayer::AudioPlayer() {}
  15. AudioPlayer::~AudioPlayer() { reset(); }
  16. bool AudioPlayer::open(const AVFrame* frame, float speed) {
  17. qDebug() << "[AUDIO-PLAYER] open: sample_rate=" << frame->sample_rate << "channels=" << frame->ch_layout.nb_channels << "format=" << frame->format << "speed=" << speed;
  18. QMutexLocker locker(&m_mutex);
  19. qDebug() << "[AUDIO-PLAYER] got mutex";
  20. reset();
  21. qDebug() << "[AUDIO-PLAYER] after reset";
  22. return initAudioOutput(frame, speed);
  23. }
  24. bool AudioPlayer::initAudioOutput(const AVFrame* frame, float speed) {
  25. qDebug() << "[AUDIO-PLAYER] initAudioOutput begin";
  26. m_sampleRate = frame->sample_rate;
  27. m_channels = frame->ch_layout.nb_channels;
  28. m_format = (AVSampleFormat)frame->format;
  29. m_speed = speed;
  30. m_volume = 1.0f;
  31. releaseSonic();
  32. ensureSonic(m_sampleRate, m_channels);
  33. setSpeed(speed);
  34. QAudioFormat fmt;
  35. fmt.setSampleRate(m_sampleRate);
  36. fmt.setChannelCount(m_channels);
  37. fmt.setSampleSize(16); // S16
  38. fmt.setCodec("audio/pcm");
  39. fmt.setByteOrder(QAudioFormat::LittleEndian);
  40. fmt.setSampleType(QAudioFormat::SignedInt);
  41. qDebug() << "[AUDIO-PLAYER] before QAudioOutput, deviceInfo isNull=" << m_deviceInfo.isNull();
  42. if (!m_deviceInfo.isNull()) {
  43. if (!m_deviceInfo.isFormatSupported(fmt)) {
  44. qWarning() << "音频格式不支持,尝试最近格式";
  45. fmt = m_deviceInfo.nearestFormat(fmt);
  46. }
  47. qDebug() << "[AUDIO-PLAYER] before QAudioOutput (custom device)";
  48. m_audioOutput = new QAudioOutput(m_deviceInfo, fmt, nullptr);
  49. } else {
  50. QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
  51. if (!info.isFormatSupported(fmt)) {
  52. qWarning() << "音频格式不支持,尝试最近格式";
  53. fmt = info.nearestFormat(fmt);
  54. }
  55. qDebug() << "[AUDIO-PLAYER] before QAudioOutput (default device)";
  56. m_audioOutput = new QAudioOutput(fmt, nullptr);
  57. }
  58. qDebug() << "[AUDIO-PLAYER] after QAudioOutput, m_audioOutput=" << m_audioOutput;
  59. // m_audioOutput->setBufferSize(16384);
  60. m_audioOutput->setVolume(m_volume);
  61. qDebug() << "[AUDIO-PLAYER] before start";
  62. m_audioDevice = m_audioOutput->start();
  63. qDebug() << "[AUDIO-PLAYER] after start, m_audioDevice=" << m_audioDevice;
  64. return m_audioDevice != nullptr;
  65. }
  66. bool AudioPlayer::play(const AVFrame* frame, float speed) {
  67. QMutexLocker locker(&m_mutex);
  68. if (!m_audioDevice) return false;
  69. if (m_sampleRate != frame->sample_rate || m_channels != frame->ch_layout.nb_channels || m_format != (AVSampleFormat)frame->format) {
  70. open(frame, speed);
  71. }
  72. m_speed = speed;
  73. setSpeed(speed);
  74. // 1. 重采样到 S16
  75. const AVSampleFormat targetFmt = AV_SAMPLE_FMT_S16;
  76. uint8_t* inputData = nullptr;
  77. int inputSamples = frame->nb_samples;
  78. int inputBytes = av_samples_get_buffer_size(nullptr, m_channels, inputSamples, targetFmt, 1);
  79. if (m_format != targetFmt) {
  80. ensureResampler(frame);
  81. if (!m_swrBuffer || m_swrBufferSize < inputBytes) {
  82. if (m_swrBuffer) av_free(m_swrBuffer);
  83. m_swrBuffer = (uint8_t*)av_malloc(inputBytes);
  84. m_swrBufferSize = inputBytes;
  85. }
  86. int outSamples = swr_convert(
  87. m_swrCtx,
  88. &m_swrBuffer, inputSamples,
  89. (const uint8_t**)frame->extended_data, inputSamples
  90. );
  91. inputData = m_swrBuffer;
  92. inputSamples = outSamples;
  93. inputBytes = av_samples_get_buffer_size(nullptr, m_channels, outSamples, targetFmt, 1);
  94. } else {
  95. inputData = frame->data[0];
  96. inputBytes = av_samples_get_buffer_size(nullptr, m_channels, inputSamples, targetFmt, 1);
  97. }
  98. // 2. 送 sonic 变速
  99. ensureSonic(m_sampleRate, m_channels);
  100. setSpeed(speed);
  101. int out_ret = sonicWriteShortToStream(m_sonicCtx, (int16_t*)inputData, inputBytes / (m_channels * 2));
  102. int num_samples = sonicSamplesAvailable(m_sonicCtx);
  103. int out_size = num_samples * 2 * m_channels;
  104. av_fast_malloc(&m_abufOut, &m_abufOutSize, out_size);
  105. int sonic_samples = 0;
  106. if (out_ret) {
  107. sonic_samples = sonicReadShortFromStream(m_sonicCtx, (int16_t*)m_abufOut, num_samples);
  108. out_size = sonic_samples * 2 * m_channels;
  109. }
  110. // 3. 写入音频设备前判断可用空间
  111. if (m_audioOutput && m_audioOutput->bytesFree() < out_size) {
  112. qWarning() << "[AUDIO] QAudioOutput 缓冲区不够,丢帧 out_size=" << out_size << "bytesFree=" << m_audioOutput->bytesFree();
  113. return false;
  114. }
  115. if (out_size > 0)
  116. m_audioDevice->write((const char*)m_abufOut, out_size);
  117. return true;
  118. }
  119. void AudioPlayer::setSpeed(float speed) {
  120. // QMutexLocker locker(&m_mutex);
  121. m_speed = speed;
  122. if (m_sonicCtx) {
  123. sonicSetSpeed(m_sonicCtx, speed);
  124. sonicSetPitch(m_sonicCtx, 1.0f);
  125. sonicSetRate(m_sonicCtx, 1.0f);
  126. }
  127. }
  128. void AudioPlayer::setVolume(float volume) {
  129. QMutexLocker locker(&m_mutex);
  130. m_volume = volume;
  131. if (m_audioOutput) {
  132. m_audioOutput->setVolume(volume);
  133. }
  134. }
  135. bool AudioPlayer::setOutputDevice(const QAudioDeviceInfo& deviceInfo) {
  136. QMutexLocker locker(&m_mutex);
  137. m_deviceInfo = deviceInfo;
  138. if (m_audioOutput) {
  139. m_audioOutput->stop();
  140. delete m_audioOutput;
  141. m_audioOutput = nullptr;
  142. }
  143. return true;
  144. }
  145. void AudioPlayer::stop() {
  146. QMutexLocker locker(&m_mutex);
  147. if (m_audioOutput) {
  148. m_audioOutput->stop();
  149. }
  150. }
  151. void AudioPlayer::reset()
  152. {
  153. releaseSonic();
  154. releaseResampler();
  155. releaseAudioOutput();
  156. if (m_abufOut) {
  157. av_freep(&m_abufOut);
  158. m_abufOut = nullptr;
  159. m_abufOutSize = 0;
  160. }
  161. m_sampleRate = 0;
  162. m_channels = 0;
  163. m_format = AV_SAMPLE_FMT_NONE;
  164. m_speed = 1.0f;
  165. m_volume = 1.0f;
  166. m_deviceInfo = QAudioDeviceInfo();
  167. }
  168. void AudioPlayer::freeBuffers() {
  169. if (m_abufOut) {
  170. av_freep(&m_abufOut);
  171. m_abufOut = nullptr;
  172. m_abufOutSize = 0;
  173. }
  174. }
  175. bool AudioPlayer::ensureResampler(const AVFrame* frame) {
  176. if (!m_swrCtx) {
  177. m_swrCtx = swr_alloc();
  178. swr_alloc_set_opts2(&m_swrCtx,
  179. &frame->ch_layout, // out_ch_layout
  180. AV_SAMPLE_FMT_S16,
  181. frame->sample_rate,
  182. &frame->ch_layout, // in_ch_layout
  183. (AVSampleFormat)frame->format,
  184. frame->sample_rate,
  185. 0,
  186. nullptr);
  187. swr_init(m_swrCtx);
  188. }
  189. return m_swrCtx != nullptr;
  190. }
  191. void AudioPlayer::releaseResampler() {
  192. if (m_swrCtx) {
  193. swr_free(&m_swrCtx);
  194. m_swrCtx = nullptr;
  195. }
  196. if (m_swrBuffer) {
  197. av_free(m_swrBuffer);
  198. m_swrBuffer = nullptr;
  199. m_swrBufferSize = 0;
  200. }
  201. }
  202. bool AudioPlayer::ensureSonic(int sampleRate, int channels) {
  203. if (!m_sonicCtx) {
  204. m_sonicCtx = sonicCreateStream(sampleRate, channels);
  205. }
  206. return m_sonicCtx != nullptr;
  207. }
  208. void AudioPlayer::releaseSonic() {
  209. if (m_sonicCtx) {
  210. sonicDestroyStream(m_sonicCtx);
  211. m_sonicCtx = nullptr;
  212. }
  213. }
  214. void AudioPlayer::releaseAudioOutput() {
  215. if (m_audioOutput) {
  216. m_audioOutput->stop();
  217. delete m_audioOutput;
  218. m_audioOutput = nullptr;
  219. }
  220. m_audioDevice = nullptr;
  221. }
  222. QIODevice* AudioPlayer::getOutputDevice() const {
  223. return m_audioDevice;
  224. }
  225. QAudioOutput* AudioPlayer::getAudioOutput() const {
  226. return m_audioOutput;
  227. }
  228. float AudioPlayer::getSpeed() const {
  229. return m_speed;
  230. }
  231. float AudioPlayer::getVolume() const {
  232. return m_volume;
  233. }