2 * Copyright (C) 2010-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
23 #include "ActiveAESink.h"
24 #include "cores/AudioEngine/Utils/AEUtil.h"
25 #include "utils/EndianSwap.h"
28 #include "settings/Settings.h"
30 using namespace ActiveAE;
32 CActiveAESink::CActiveAESink(CEvent *inMsgEvent) :
34 m_controlPort("SinkControlPort", inMsgEvent, &m_outMsgEvent),
35 m_dataPort("SinkDataPort", inMsgEvent, &m_outMsgEvent)
37 m_inMsgEvent = inMsgEvent;
40 m_convertBuffer = NULL;
44 void CActiveAESink::Start()
49 SetPriority(THREAD_PRIORITY_ABOVE_NORMAL);
53 void CActiveAESink::Dispose()
58 m_controlPort.Purge();
64 m_sink->Deinitialize();
69 delete m_sampleOfSilence.pkt;
70 m_sampleOfSilence.pkt = NULL;
74 _aligned_free(m_convertBuffer);
75 m_convertBuffer = NULL;
79 AEDeviceType CActiveAESink::GetDeviceType(const std::string &device)
81 std::string dev = device;
83 CAESinkFactory::ParseDevice(dev, dri);
84 for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
86 for (AEDeviceInfoList::iterator itt2 = itt->m_deviceInfoList.begin(); itt2 != itt->m_deviceInfoList.end(); ++itt2)
88 CAEDeviceInfo& info = *itt2;
89 if (info.m_deviceName == dev)
90 return info.m_deviceType;
93 return AE_DEVTYPE_PCM;
96 bool CActiveAESink::HasPassthroughDevice()
98 for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
100 for (AEDeviceInfoList::iterator itt2 = itt->m_deviceInfoList.begin(); itt2 != itt->m_deviceInfoList.end(); ++itt2)
102 CAEDeviceInfo& info = *itt2;
103 if (info.m_deviceType != AE_DEVTYPE_PCM)
110 bool CActiveAESink::SupportsFormat(const std::string &device, AEDataFormat format)
112 std::string dev = device;
114 CAESinkFactory::ParseDevice(dev, dri);
115 for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
117 if (dri == itt->m_sinkName)
119 for (AEDeviceInfoList::iterator itt2 = itt->m_deviceInfoList.begin(); itt2 != itt->m_deviceInfoList.end(); ++itt2)
121 CAEDeviceInfo& info = *itt2;
122 if (info.m_deviceName == dev)
124 AEDataFormatList::iterator itt3;
125 itt3 = find(info.m_dataFormats.begin(), info.m_dataFormats.end(), format);
126 if (itt3 != info.m_dataFormats.end())
140 S_TOP_UNCONFIGURED, // 1
141 S_TOP_CONFIGURED, // 2
142 S_TOP_CONFIGURED_SUSPEND, // 3
143 S_TOP_CONFIGURED_IDLE, // 4
144 S_TOP_CONFIGURED_PLAY, // 5
145 S_TOP_CONFIGURED_SILENCE, // 6
148 int SINK_parentStates[] = {
150 0, //TOP_UNCONFIGURED
152 2, //TOP_CONFIGURED_SUSPEND
153 2, //TOP_CONFIGURED_IDLE
154 2, //TOP_CONFIGURED_PLAY
155 2, //TOP_CONFIGURED_SILENCE
158 void CActiveAESink::StateMachine(int signal, Protocol *port, Message *msg)
160 for (int state = m_state; ; state = SINK_parentStates[state])
165 if (port == &m_controlPort)
169 case CSinkControlProtocol::CONFIGURE:
171 data = (SinkConfig*)msg->data;
174 m_requestedFormat = data->format;
175 m_stats = data->stats;
176 m_device = *(data->device);
179 m_extSilenceTimer = 0;
180 m_extStreaming = false;
187 reply.format = m_sinkFormat;
188 reply.cacheTotal = m_sink->GetCacheTotal();
189 reply.latency = m_sink->GetLatency();
190 reply.hasVolume = m_sink->HasVolume();
191 m_state = S_TOP_CONFIGURED_IDLE;
192 m_extTimeout = 10000;
193 msg->Reply(CSinkControlProtocol::ACC, &reply, sizeof(SinkReply));
197 m_state = S_TOP_UNCONFIGURED;
198 msg->Reply(CSinkControlProtocol::ERR);
202 case CSinkControlProtocol::UNCONFIGURE:
207 m_sink->Deinitialize();
211 m_state = S_TOP_UNCONFIGURED;
212 msg->Reply(CSinkControlProtocol::ACC);
215 case CSinkControlProtocol::FLUSH:
217 msg->Reply(CSinkControlProtocol::ACC);
220 case CSinkControlProtocol::APPFOCUSED:
221 m_extAppFocused = *(bool*)msg->data;
230 else if (port == &m_dataPort)
234 case CSinkDataProtocol::DRAIN:
235 msg->Reply(CSinkDataProtocol::ACC);
236 m_state = S_TOP_UNCONFIGURED;
244 std::string portName = port == NULL ? "timer" : port->portName;
245 CLog::Log(LOGWARNING, "CActiveAESink::%s - signal: %d form port: %s not handled for state: %d", __FUNCTION__, signal, portName.c_str(), m_state);
249 case S_TOP_UNCONFIGURED:
250 if (port == NULL) // timeout
254 case CSinkControlProtocol::TIMEOUT:
261 else if (port == &m_dataPort)
265 case CSinkDataProtocol::SAMPLE:
266 CSampleBuffer *samples;
268 samples = *((CSampleBuffer**)msg->data);
269 timeout = 1000*samples->pkt->nb_samples/samples->pkt->config.sample_rate;
271 msg->Reply(CSinkDataProtocol::RETURNSAMPLE, &samples, sizeof(CSampleBuffer*));
280 case S_TOP_CONFIGURED:
281 if (port == &m_controlPort)
285 case CSinkControlProtocol::STREAMING:
286 m_extStreaming = *(bool*)msg->data;
288 if (!m_extSilenceTimer.IsTimePast())
290 m_state = S_TOP_CONFIGURED_SILENCE;
294 case CSinkControlProtocol::VOLUME:
295 m_volume = *(float*)msg->data;
296 m_sink->SetVolume(m_volume);
302 else if (port == &m_dataPort)
306 case CSinkDataProtocol::DRAIN:
308 msg->Reply(CSinkDataProtocol::ACC);
309 m_state = S_TOP_CONFIGURED_IDLE;
310 m_extTimeout = 10000;
312 case CSinkDataProtocol::SAMPLE:
313 CSampleBuffer *samples;
315 samples = *((CSampleBuffer**)msg->data);
316 delay = OutputSamples(samples);
317 msg->Reply(CSinkDataProtocol::RETURNSAMPLE, &samples, sizeof(CSampleBuffer*));
320 m_sink->Deinitialize();
323 m_state = S_TOP_CONFIGURED_SUSPEND;
328 m_state = S_TOP_CONFIGURED_PLAY;
329 m_extTimeout = delay / 2;
330 m_extSilenceTimer.Set(m_extSilenceTimeout);
339 case S_TOP_CONFIGURED_SUSPEND:
340 if (port == &m_controlPort)
344 case CSinkControlProtocol::STREAMING:
345 m_extStreaming = *(bool*)msg->data;
349 case CSinkControlProtocol::VOLUME:
350 m_volume = *(float*)msg->data;
356 else if (port == &m_dataPort)
360 case CSinkDataProtocol::SAMPLE:
363 OutputSamples(&m_sampleOfSilence);
364 m_state = S_TOP_CONFIGURED_PLAY;
366 m_bStateMachineSelfTrigger = true;
368 case CSinkDataProtocol::DRAIN:
369 msg->Reply(CSinkDataProtocol::ACC);
375 else if (port == NULL) // timeout
379 case CSinkControlProtocol::TIMEOUT:
380 m_extTimeout = 10000;
388 case S_TOP_CONFIGURED_IDLE:
389 if (port == &m_dataPort)
393 case CSinkDataProtocol::SAMPLE:
394 OutputSamples(&m_sampleOfSilence);
395 m_state = S_TOP_CONFIGURED_PLAY;
397 m_bStateMachineSelfTrigger = true;
403 else if (port == NULL) // timeout
407 case CSinkControlProtocol::TIMEOUT:
408 m_sink->Deinitialize();
411 m_state = S_TOP_CONFIGURED_SUSPEND;
412 m_extTimeout = 10000;
420 case S_TOP_CONFIGURED_PLAY:
421 if (port == NULL) // timeout
425 case CSinkControlProtocol::TIMEOUT:
426 if (!m_extSilenceTimer.IsTimePast())
428 m_state = S_TOP_CONFIGURED_SILENCE;
434 m_state = S_TOP_CONFIGURED_IDLE;
436 m_extTimeout = 10000;
447 case S_TOP_CONFIGURED_SILENCE:
448 if (port == NULL) // timeout
452 case CSinkControlProtocol::TIMEOUT:
453 OutputSamples(&m_sampleOfSilence);
456 m_sink->Deinitialize();
459 m_state = S_TOP_CONFIGURED_SUSPEND;
462 m_state = S_TOP_CONFIGURED_PLAY;
471 default: // we are in no state, should not happen
472 CLog::Log(LOGERROR, "CActiveAESink::%s - no valid state: %d", __FUNCTION__, m_state);
478 void CActiveAESink::Process()
481 Protocol *port = NULL;
483 XbmcThreads::EndTime timer;
485 m_state = S_TOP_UNCONFIGURED;
487 m_bStateMachineSelfTrigger = false;
488 m_extAppFocused = true;
493 timer.Set(m_extTimeout);
495 if (m_bStateMachineSelfTrigger)
497 m_bStateMachineSelfTrigger = false;
498 // self trigger state machine
499 StateMachine(msg->signal, port, msg);
500 if (!m_bStateMachineSelfTrigger)
507 // check control port
508 else if (m_controlPort.ReceiveOutMessage(&msg))
511 port = &m_controlPort;
514 else if (m_dataPort.ReceiveOutMessage(&msg))
522 StateMachine(msg->signal, port, msg);
523 if (!m_bStateMachineSelfTrigger)
532 else if (m_outMsgEvent.WaitMSec(m_extTimeout))
534 m_extTimeout = timer.MillisLeft();
540 msg = m_controlPort.GetMessage();
541 msg->signal = CSinkControlProtocol::TIMEOUT;
543 // signal timeout to state machine
544 StateMachine(msg->signal, port, msg);
545 if (!m_bStateMachineSelfTrigger)
554 void CActiveAESink::EnumerateSinkList(bool force)
556 if (!m_sinkInfoList.empty() && !force)
559 unsigned int c_retry = 4;
560 m_sinkInfoList.clear();
561 CAESinkFactory::EnumerateEx(m_sinkInfoList);
562 while(m_sinkInfoList.size() == 0 && c_retry > 0)
564 CLog::Log(LOGNOTICE, "No Devices found - retry: %d", c_retry);
567 // retry the enumeration
568 CAESinkFactory::EnumerateEx(m_sinkInfoList, true);
570 CLog::Log(LOGNOTICE, "Found %lu Lists of Devices", m_sinkInfoList.size());
574 void CActiveAESink::PrintSinks()
576 for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
578 CLog::Log(LOGNOTICE, "Enumerated %s devices:", itt->m_sinkName.c_str());
580 for (AEDeviceInfoList::iterator itt2 = itt->m_deviceInfoList.begin(); itt2 != itt->m_deviceInfoList.end(); ++itt2)
582 CLog::Log(LOGNOTICE, " Device %d", ++count);
583 CAEDeviceInfo& info = *itt2;
584 std::stringstream ss((std::string)info);
586 while(std::getline(ss, line, '\n'))
587 CLog::Log(LOGNOTICE, " %s", line.c_str());
592 void CActiveAESink::EnumerateOutputDevices(AEDeviceList &devices, bool passthrough)
594 EnumerateSinkList(false);
596 for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
598 AESinkInfo sinkInfo = *itt;
599 for (AEDeviceInfoList::iterator itt2 = sinkInfo.m_deviceInfoList.begin(); itt2 != sinkInfo.m_deviceInfoList.end(); ++itt2)
601 CAEDeviceInfo devInfo = *itt2;
602 if (passthrough && devInfo.m_deviceType == AE_DEVTYPE_PCM)
605 std::string device = sinkInfo.m_sinkName + ":" + devInfo.m_deviceName;
607 std::stringstream ss;
609 /* add the sink name if we have more then one sink type */
610 if (m_sinkInfoList.size() > 1)
611 ss << sinkInfo.m_sinkName << ": ";
613 ss << devInfo.m_displayName;
614 if (!devInfo.m_displayNameExtra.empty())
615 ss << ", " << devInfo.m_displayNameExtra;
617 devices.push_back(AEDevice(ss.str(), device));
622 std::string CActiveAESink::GetDefaultDevice(bool passthrough)
624 EnumerateSinkList(false);
626 for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
628 AESinkInfo sinkInfo = *itt;
629 for (AEDeviceInfoList::iterator itt2 = sinkInfo.m_deviceInfoList.begin(); itt2 != sinkInfo.m_deviceInfoList.end(); ++itt2)
631 CAEDeviceInfo devInfo = *itt2;
632 if (passthrough && devInfo.m_deviceType == AE_DEVTYPE_PCM)
635 std::string device = sinkInfo.m_sinkName + ":" + devInfo.m_deviceName;
642 void CActiveAESink::GetDeviceFriendlyName(std::string &device)
644 m_deviceFriendlyName = "Device not found";
645 /* Match the device and find its friendly name */
646 for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
648 AESinkInfo sinkInfo = *itt;
649 for (AEDeviceInfoList::iterator itt2 = sinkInfo.m_deviceInfoList.begin(); itt2 != sinkInfo.m_deviceInfoList.end(); ++itt2)
651 CAEDeviceInfo& devInfo = *itt2;
652 if (devInfo.m_deviceName == device)
654 m_deviceFriendlyName = devInfo.m_displayName;
662 void CActiveAESink::OpenSink()
664 // we need a copy of m_device here because ParseDevice and CreateDevice write back
665 // into this variable
666 std::string device = m_device;
668 bool passthrough = AE_IS_RAW(m_requestedFormat.m_dataFormat);
670 CAESinkFactory::ParseDevice(device, driver);
671 if (driver.empty() && m_sink)
672 driver = m_sink->GetName();
674 CLog::Log(LOGINFO, "CActiveAESink::OpenSink - initialize sink");
679 m_sink->Deinitialize();
684 // get the display name of the device
685 GetDeviceFriendlyName(device);
687 // if we already have a driver, prepend it to the device string
689 device = driver + ":" + device;
691 // WARNING: this changes format and does not use passthrough
692 m_sinkFormat = m_requestedFormat;
693 CLog::Log(LOGDEBUG, "CActiveAESink::OpenSink - trying to open device %s", device.c_str());
694 m_sink = CAESinkFactory::Create(device, m_sinkFormat, passthrough);
696 // try first device in out list
697 if (!m_sink && !m_sinkInfoList.empty())
699 driver = m_sinkInfoList.front().m_sinkName;
700 device = m_sinkInfoList.front().m_deviceInfoList.front().m_deviceName;
701 GetDeviceFriendlyName(device);
703 device = driver + ":" + device;
704 m_sinkFormat = m_requestedFormat;
705 CLog::Log(LOGDEBUG, "CActiveAESink::OpenSink - trying to open device %s", device.c_str());
706 m_sink = CAESinkFactory::Create(device, m_sinkFormat, passthrough);
710 // TODO: should not be required by ActiveAE
713 device = "NULL:NULL";
714 m_sinkFormat = m_requestedFormat;
715 CLog::Log(LOGDEBUG, "CActiveAESink::OpenSink - open NULL sink");
716 m_sink = CAESinkFactory::Create(device, m_sinkFormat, passthrough);
721 CLog::Log(LOGERROR, "CActiveAESink::OpenSink - no sink was returned");
726 m_sink->SetVolume(m_volume);
728 #ifdef WORDS_BIGENDIAN
729 if (m_sinkFormat.m_dataFormat == AE_FMT_S16BE)
730 m_sinkFormat.m_dataFormat = AE_FMT_S16NE;
731 else if (m_sinkFormat.m_dataFormat == AE_FMT_S32BE)
732 m_sinkFormat.m_dataFormat = AE_FMT_S32NE;
734 if (m_sinkFormat.m_dataFormat == AE_FMT_S16LE)
735 m_sinkFormat.m_dataFormat = AE_FMT_S16NE;
736 else if (m_sinkFormat.m_dataFormat == AE_FMT_S32LE)
737 m_sinkFormat.m_dataFormat = AE_FMT_S32NE;
740 CLog::Log(LOGDEBUG, "CActiveAESink::OpenSink - %s Initialized:", m_sink->GetName());
741 CLog::Log(LOGDEBUG, " Output Device : %s", m_deviceFriendlyName.c_str());
742 CLog::Log(LOGDEBUG, " Sample Rate : %d", m_sinkFormat.m_sampleRate);
743 CLog::Log(LOGDEBUG, " Sample Format : %s", CAEUtil::DataFormatToStr(m_sinkFormat.m_dataFormat));
744 CLog::Log(LOGDEBUG, " Channel Count : %d", m_sinkFormat.m_channelLayout.Count());
745 CLog::Log(LOGDEBUG, " Channel Layout: %s", ((std::string)m_sinkFormat.m_channelLayout).c_str());
746 CLog::Log(LOGDEBUG, " Frames : %d", m_sinkFormat.m_frames);
747 CLog::Log(LOGDEBUG, " Frame Samples : %d", m_sinkFormat.m_frameSamples);
748 CLog::Log(LOGDEBUG, " Frame Size : %d", m_sinkFormat.m_frameSize);
750 // init sample of silence
752 config.fmt = CActiveAEResample::GetAVSampleFormat(m_sinkFormat.m_dataFormat);
753 config.bits_per_sample = CAEUtil::DataFormatToUsedBits(m_sinkFormat.m_dataFormat);
754 config.channel_layout = CActiveAEResample::GetAVChannelLayout(m_sinkFormat.m_channelLayout);
755 config.channels = m_sinkFormat.m_channelLayout.Count();
756 config.sample_rate = m_sinkFormat.m_sampleRate;
758 // init sample of silence/noise
759 delete m_sampleOfSilence.pkt;
760 m_sampleOfSilence.pkt = new CSoundPacket(config, m_sinkFormat.m_frames);
761 m_sampleOfSilence.pkt->nb_samples = m_sampleOfSilence.pkt->max_nb_samples;
767 _aligned_free(m_convertBuffer);
768 m_convertBuffer = NULL;
771 m_convertState = CHECK_CONVERT;
774 void CActiveAESink::ReturnBuffers()
777 CSampleBuffer *samples;
778 while (m_dataPort.ReceiveOutMessage(&msg))
780 if (msg->signal == CSinkDataProtocol::SAMPLE)
782 samples = *((CSampleBuffer**)msg->data);
783 msg->Reply(CSinkDataProtocol::RETURNSAMPLE, &samples, sizeof(CSampleBuffer*));
788 unsigned int CActiveAESink::OutputSamples(CSampleBuffer* samples)
790 uint8_t *buffer = samples->pkt->data[0];
791 unsigned int frames = samples->pkt->nb_samples;
792 unsigned int maxFrames;
794 unsigned int written = 0;
795 double sinkDelay = 0.0;
797 switch(m_convertState)
802 EnsureConvertBuffer(samples);
803 buffer = Convert(samples);
806 Endian_Swap16_buf((uint16_t *)buffer, (uint16_t *)buffer, frames * samples->pkt->config.channels);
809 ConvertInit(samples);
810 if (m_convertState == NEED_CONVERT)
811 buffer = Convert(samples);
812 else if (m_convertState == NEED_BYTESWAP)
813 Endian_Swap16_buf((uint16_t *)buffer, (uint16_t *)buffer, frames * samples->pkt->config.channels);
821 maxFrames = std::min(frames, m_sinkFormat.m_frames);
822 written = m_sink->AddPackets(buffer, maxFrames, true, true);
825 Sleep(500*m_sinkFormat.m_frames/m_sinkFormat.m_sampleRate);
830 CLog::Log(LOGERROR, "CActiveAESink::OutputSamples - failed");
831 m_stats->UpdateSinkDelay(0, frames);
837 else if (written > maxFrames)
840 CLog::Log(LOGERROR, "CActiveAESink::OutputSamples - sink returned error");
841 m_stats->UpdateSinkDelay(0, samples->pool ? maxFrames : 0);
845 buffer += written*m_sinkFormat.m_frameSize;
846 sinkDelay = m_sink->GetDelay();
847 m_stats->UpdateSinkDelay(sinkDelay, samples->pool ? written : 0);
849 return sinkDelay*1000;
852 void CActiveAESink::ConvertInit(CSampleBuffer* samples)
854 if (CActiveAEResample::GetAESampleFormat(samples->pkt->config.fmt, samples->pkt->config.bits_per_sample) != m_sinkFormat.m_dataFormat)
856 m_convertFn = CAEConvert::FrFloat(m_sinkFormat.m_dataFormat);
858 _aligned_free(m_convertBuffer);
859 m_convertBufferSampleSize = samples->pkt->max_nb_samples;
860 m_convertBuffer = (uint8_t*)_aligned_malloc(samples->pkt->max_nb_samples * m_sinkFormat.m_channelLayout.Count() * m_sinkFormat.m_frameSize, 16);
861 memset(m_convertBuffer, 0, samples->pkt->max_nb_samples * m_sinkFormat.m_channelLayout.Count() * m_sinkFormat.m_frameSize);
862 m_convertState = NEED_CONVERT;
864 else if (AE_IS_RAW(m_requestedFormat.m_dataFormat) && CAEUtil::S16NeedsByteSwap(AE_FMT_S16NE, m_sinkFormat.m_dataFormat))
866 m_convertState = NEED_BYTESWAP;
869 m_convertState = SKIP_CONVERT;
872 void CActiveAESink::EnsureConvertBuffer(CSampleBuffer* samples)
874 if (!m_convertBuffer)
877 if (samples->pkt->max_nb_samples <= m_convertBufferSampleSize)
880 _aligned_free(m_convertBuffer);
881 m_convertBufferSampleSize = samples->pkt->max_nb_samples;
882 m_convertBuffer = (uint8_t*)_aligned_malloc(samples->pkt->max_nb_samples * m_sinkFormat.m_channelLayout.Count() * m_sinkFormat.m_frameSize, 16);
883 memset(m_convertBuffer, 0, samples->pkt->max_nb_samples * m_sinkFormat.m_channelLayout.Count() * m_sinkFormat.m_frameSize);
886 uint8_t* CActiveAESink::Convert(CSampleBuffer* samples)
888 m_convertFn((float*)samples->pkt->data[0], samples->pkt->nb_samples * samples->pkt->config.channels, m_convertBuffer);
889 return m_convertBuffer;
892 #define PI 3.1415926536f
894 void CActiveAESink::GenerateNoise()
896 int nb_floats = m_sinkFormat.m_frames*m_sinkFormat.m_channelLayout.Count();
897 float *noise = (float*)_aligned_malloc(nb_floats*sizeof(float), 16);
900 for(int i=0; i<nb_floats;i++)
904 R1 = (float) rand() / (float) RAND_MAX;
905 R2 = (float) rand() / (float) RAND_MAX;
909 noise[i] = (float) sqrt( -2.0f * log( R1 )) * cos( 2.0f * PI * R2 ) * 0.00001f;
912 AEDataFormat fmt = CActiveAEResample::GetAESampleFormat(m_sampleOfSilence.pkt->config.fmt, m_sampleOfSilence.pkt->config.bits_per_sample);
913 CAEConvert::AEConvertFrFn convertFn = CAEConvert::FrFloat(fmt);
914 convertFn(noise, nb_floats, m_sampleOfSilence.pkt->data[0]);
915 _aligned_free(noise);
918 void CActiveAESink::SetSilenceTimer()
921 m_extSilenceTimeout = XbmcThreads::EndTime::InfiniteValue;
922 else if (m_extAppFocused)
923 m_extSilenceTimeout = CSettings::Get().GetInt("audiooutput.streamsilence") * 60000;
925 m_extSilenceTimeout = 0;
926 m_extSilenceTimer.Set(m_extSilenceTimeout);