GEAudioOut.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /*
  2. * Copyright (c) 2011 Nokia Corporation.
  3. */
  4. #include <QtCore/QDebug>
  5. #include <QtCore/qstring.h>
  6. #include <QAudioOutput>
  7. #include <QAudioFormat>
  8. #include "GEAudioOut.h"
  9. #ifdef USE_VOLUMEHACK_WARNING_MIGHT_CRASH_WITH_DIFFERENT_SDK
  10. #ifdef Q_OS_SYMBIAN
  11. #include <SoundDevice.h>
  12. #endif
  13. #endif
  14. using namespace GF;
  15. const int CHANNELS = 2;
  16. const QString CODEC = "audio/pcm";
  17. const QAudioFormat::Endian BYTEORDER = QAudioFormat::LittleEndian;
  18. const QAudioFormat::SampleType SAMTYPE = QAudioFormat::SignedInt;
  19. AudioOut::AudioOut(QObject *parent, GF::IAudioSource *source)
  20. : QThread(parent)
  21. {
  22. m_source = source;
  23. m_usingThread = false;
  24. QAudioFormat format;
  25. format.setFrequency(AUDIO_FREQUENCY);
  26. format.setChannels(CHANNELS);
  27. format.setSampleSize(AUDIO_SAMPLE_BITS);
  28. format.setCodec(CODEC);
  29. format.setByteOrder(BYTEORDER);
  30. format.setSampleType(SAMTYPE);
  31. QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
  32. if (!info.isFormatSupported(format)) {
  33. //qDebug() << "DEBUG: Audio format WAS NOT supported";
  34. format = info.nearestFormat(format);
  35. }
  36. m_audioOutput = new QAudioOutput(info, format);
  37. #if defined(Q_WS_MAEMO_5) || defined(MY_OS_MEEGO)
  38. m_sendBufferSize = 4096*4;
  39. #else
  40. m_audioOutput->setBufferSize(4096*4);
  41. #endif
  42. m_outTarget = m_audioOutput->start();
  43. //m_audioOutput->setBufferSize( 262144 );
  44. #if defined(Q_WS_MAEMO_5) || defined(MY_OS_MEEGO)
  45. m_audioOutput->setBufferSize(4096*16);
  46. m_sendBufferSize = 4096*8;
  47. #else
  48. m_audioOutput->setBufferSize(4096*4);
  49. m_sendBufferSize = 4096*2;
  50. #endif
  51. m_sendBuffer = new AUDIO_SAMPLE_TYPE[m_sendBufferSize];
  52. m_samplesMixed = 0;
  53. m_runstate = 0;
  54. #ifndef Q_OS_SYMBIAN
  55. m_usingThread = true;
  56. start();
  57. #else
  58. m_audioOutput->setNotifyInterval(5);
  59. connect(m_audioOutput, SIGNAL(notify()), this, SLOT(audioNotify()));
  60. #ifdef USE_VOLUMEHACK_WARNING_MIGHT_CRASH_WITH_DIFFERENT_SDK
  61. qDebug() << "Using voluemehack... WARNING, this might cause application to crash if SDK is different than the hack is designed for. Undef USE_VOLUMEHACK_WARNING_MIGHT_CRASH_WITH_DIFFERENT_SDK to disable hack..";
  62. /*
  63. WARNING!!!!!!
  64. Really ugly hack is used as a last resort. This allows us to adjust the
  65. application volume in Symbian. The CMMFDevSound object lies deep
  66. inside the QAudioOutput in Symbian implementation and it has the needed
  67. functions. So we get the needed object accessing directly from memory.
  68. */
  69. unsigned int *pointer_to_abstract_audio =
  70. (unsigned int*)((unsigned char*)m_audioOutput + 8);
  71. unsigned int *dev_sound_wrapper =
  72. (unsigned int*)(*pointer_to_abstract_audio) + 13;
  73. unsigned int *temp = ((unsigned int*)(*dev_sound_wrapper) + 6);
  74. CMMFDevSound *dev_sound = (CMMFDevSound*)(*temp);
  75. dev_sound->SetVolume(dev_sound->MaxVolume());
  76. #endif
  77. #endif
  78. }
  79. AudioOut::~AudioOut()
  80. {
  81. if (m_runstate == 0)
  82. m_runstate = 1;
  83. if (QThread::isRunning() == false)
  84. m_runstate = 2;
  85. else
  86. wait(5000);
  87. m_outTarget->close();
  88. m_audioOutput->stop();
  89. delete m_audioOutput;
  90. delete [] m_sendBuffer;
  91. }
  92. void AudioOut::audioNotify()
  93. {
  94. tick();
  95. }
  96. void AudioOut::tick()
  97. {
  98. // fill data to buffer as much as free space is available..
  99. int samplesToWrite = m_audioOutput->bytesFree() /
  100. (CHANNELS*AUDIO_SAMPLE_BITS/8);
  101. samplesToWrite *= 2;
  102. if (samplesToWrite <= 0)
  103. return;
  104. if (samplesToWrite > m_sendBufferSize)
  105. samplesToWrite = m_sendBufferSize;
  106. int mixedSamples = m_source->pullAudio(m_sendBuffer, samplesToWrite);
  107. int wrote = m_outTarget->write((char*)m_sendBuffer, mixedSamples * 2);
  108. }
  109. void AudioOut::run()
  110. {
  111. //qDebug() << "Starting AudioUpdate thread.";
  112. if (!m_source) {
  113. m_runstate = 2;
  114. return;
  115. }
  116. int sleepTime = 1;
  117. while (m_runstate == 0) {
  118. tick();
  119. msleep(sleepTime);
  120. }
  121. //qDebug() << "Exiting AudioUpdate thread.";
  122. m_runstate = 2;
  123. }