[release] version bump to 13.0 beta1
[vuplus_xbmc] / xbmc / cores / AudioEngine / Engines / ActiveAE / ActiveAESink.cpp
1 /*
2  *      Copyright (C) 2010-2013 Team XBMC
3  *      http://xbmc.org
4  *
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)
8  *  any later version.
9  *
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.
14  *
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/>.
18  *
19  */
20
21 #include <sstream>
22
23 #include "ActiveAESink.h"
24 #include "Utils/AEUtil.h"
25 #include "utils/EndianSwap.h"
26 #include "ActiveAE.h"
27
28 #include "settings/Settings.h"
29
30 using namespace ActiveAE;
31
32 CActiveAESink::CActiveAESink(CEvent *inMsgEvent) :
33   CThread("AESink"),
34   m_controlPort("SinkControlPort", inMsgEvent, &m_outMsgEvent),
35   m_dataPort("SinkDataPort", inMsgEvent, &m_outMsgEvent)
36 {
37   m_inMsgEvent = inMsgEvent;
38   m_sink = NULL;
39   m_stats = NULL;
40   m_convertBuffer = NULL;
41   m_volume = 0.0;
42 }
43
44 void CActiveAESink::Start()
45 {
46   if (!IsRunning())
47   {
48     Create();
49     SetPriority(THREAD_PRIORITY_ABOVE_NORMAL);
50   }
51 }
52
53 void CActiveAESink::Dispose()
54 {
55   m_bStop = true;
56   m_outMsgEvent.Set();
57   StopThread();
58   m_controlPort.Purge();
59   m_dataPort.Purge();
60
61   if (m_sink)
62   {
63     m_sink->Drain();
64     m_sink->Deinitialize();
65     delete m_sink;
66     m_sink = NULL;
67   }
68
69   delete m_sampleOfSilence.pkt;
70   m_sampleOfSilence.pkt = NULL;
71
72   if (m_convertBuffer)
73   {
74     _aligned_free(m_convertBuffer);
75     m_convertBuffer = NULL;
76   }
77 }
78
79 bool CActiveAESink::HasVolume()
80 {
81   if (!m_sink)
82     return false;
83   return m_sink->HasVolume();
84 }
85
86 AEDeviceType CActiveAESink::GetDeviceType(const std::string &device)
87 {
88   std::string dev = device;
89   std::string dri;
90   CAESinkFactory::ParseDevice(dev, dri);
91   for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
92   {
93     for (AEDeviceInfoList::iterator itt2 = itt->m_deviceInfoList.begin(); itt2 != itt->m_deviceInfoList.end(); ++itt2)
94     {
95       CAEDeviceInfo& info = *itt2;
96       if (info.m_deviceName == dev)
97         return info.m_deviceType;
98     }
99   }
100   return AE_DEVTYPE_PCM;
101 }
102
103 bool CActiveAESink::HasPassthroughDevice()
104 {
105   for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
106   {
107     for (AEDeviceInfoList::iterator itt2 = itt->m_deviceInfoList.begin(); itt2 != itt->m_deviceInfoList.end(); ++itt2)
108     {
109       CAEDeviceInfo& info = *itt2;
110       if (info.m_deviceType != AE_DEVTYPE_PCM)
111         return true;
112     }
113   }
114   return false;
115 }
116
117 enum SINK_STATES
118 {
119   S_TOP = 0,                      // 0
120   S_TOP_UNCONFIGURED,             // 1
121   S_TOP_CONFIGURED,               // 2
122   S_TOP_CONFIGURED_SUSPEND,       // 3
123   S_TOP_CONFIGURED_IDLE,          // 4
124   S_TOP_CONFIGURED_PLAY,          // 5
125   S_TOP_CONFIGURED_SILENCE,       // 6
126 };
127
128 int SINK_parentStates[] = {
129     -1,
130     0, //TOP_UNCONFIGURED
131     0, //TOP_CONFIGURED
132     2, //TOP_CONFIGURED_SUSPEND
133     2, //TOP_CONFIGURED_IDLE
134     2, //TOP_CONFIGURED_PLAY
135     2, //TOP_CONFIGURED_SILENCE
136 };
137
138 void CActiveAESink::StateMachine(int signal, Protocol *port, Message *msg)
139 {
140   for (int state = m_state; ; state = SINK_parentStates[state])
141   {
142     switch (state)
143     {
144     case S_TOP: // TOP
145       if (port == &m_controlPort)
146       {
147         switch (signal)
148         {
149         case CSinkControlProtocol::CONFIGURE:
150           SinkConfig *data;
151           data = (SinkConfig*)msg->data;
152           if (data)
153           {
154             m_requestedFormat = data->format;
155             m_stats = data->stats;
156             m_device = *(data->device);
157           }
158           m_extError = false;
159           m_extSilenceTimer = 0;
160           ReturnBuffers();
161           OpenSink();
162
163           if (!m_extError)
164           {
165             m_stats->SetSinkCacheTotal(m_sink->GetCacheTotal());
166             m_stats->SetSinkLatency(m_sink->GetLatency());
167             m_state = S_TOP_CONFIGURED_IDLE;
168             m_extTimeout = 10000;
169             msg->Reply(CSinkControlProtocol::ACC, &m_sinkFormat, sizeof(AEAudioFormat));
170           }
171           else
172           {
173             m_state = S_TOP_UNCONFIGURED;
174             msg->Reply(CSinkControlProtocol::ERR);
175           }
176           return;
177
178         case CSinkControlProtocol::UNCONFIGURE:
179           ReturnBuffers();
180           if (m_sink)
181           {
182             m_sink->Drain();
183             m_sink->Deinitialize();
184             delete m_sink;
185             m_sink = NULL;
186           }
187           m_state = S_TOP_UNCONFIGURED;
188           msg->Reply(CSinkControlProtocol::ACC);
189           return;
190
191         case CSinkControlProtocol::FLUSH:
192           ReturnBuffers();
193           msg->Reply(CSinkControlProtocol::ACC);
194           return;
195
196         default:
197           break;
198         }
199       }
200       else if (port == &m_dataPort)
201       {
202         switch (signal)
203         {
204         case CSinkDataProtocol::DRAIN:
205           msg->Reply(CSinkDataProtocol::ACC);
206           m_state = S_TOP_UNCONFIGURED;
207           m_extTimeout = 0;
208           return;
209         default:
210           break;
211         }
212       }
213       {
214         std::string portName = port == NULL ? "timer" : port->portName;
215         CLog::Log(LOGWARNING, "CActiveAESink::%s - signal: %d form port: %s not handled for state: %d", __FUNCTION__, signal, portName.c_str(), m_state);
216       }
217       return;
218
219     case S_TOP_UNCONFIGURED:
220       if (port == NULL) // timeout
221       {
222         switch (signal)
223         {
224         case CSinkControlProtocol::TIMEOUT:
225           m_extTimeout = 1000;
226           return;
227         default:
228           break;
229         }
230       }
231       else if (port == &m_dataPort)
232       {
233         switch (signal)
234         {
235         case CSinkDataProtocol::SAMPLE:
236           CSampleBuffer *samples;
237           int timeout;
238           samples = *((CSampleBuffer**)msg->data);
239           timeout = 1000*samples->pkt->nb_samples/samples->pkt->config.sample_rate;
240           Sleep(timeout);
241           msg->Reply(CSinkDataProtocol::RETURNSAMPLE, &samples, sizeof(CSampleBuffer*));
242           m_extTimeout = 0;
243           return;
244         default:
245           break;
246         }
247       }
248       break;
249
250     case S_TOP_CONFIGURED:
251       if (port == &m_controlPort)
252       {
253         switch (signal)
254         {
255         case CSinkControlProtocol::SILENCEMODE:
256           bool silencemode;
257           silencemode = *(bool*)msg->data;
258           if (silencemode)
259             m_extSilenceTimeout = XbmcThreads::EndTime::InfiniteValue;
260           else
261             m_extSilenceTimeout = CSettings::Get().GetInt("audiooutput.streamsilence") * 60000;
262           m_extSilenceTimer.Set(m_extSilenceTimeout);
263           if (!m_extSilenceTimer.IsTimePast())
264           {
265             m_state = S_TOP_CONFIGURED_SILENCE;
266             m_extTimeout = 0;
267           }
268           return;
269         case CSinkControlProtocol::VOLUME:
270           m_volume = *(float*)msg->data;
271           m_sink->SetVolume(m_volume);
272           return;
273         default:
274           break;
275         }
276       }
277       else if (port == &m_dataPort)
278       {
279         switch (signal)
280         {
281         case CSinkDataProtocol::DRAIN:
282           m_sink->Drain();
283           msg->Reply(CSinkDataProtocol::ACC);
284           m_state = S_TOP_CONFIGURED_IDLE;
285           m_extTimeout = 10000;
286           return;
287         case CSinkDataProtocol::SAMPLE:
288           CSampleBuffer *samples;
289           unsigned int delay;
290           samples = *((CSampleBuffer**)msg->data);
291           delay = OutputSamples(samples);
292           msg->Reply(CSinkDataProtocol::RETURNSAMPLE, &samples, sizeof(CSampleBuffer*));
293           if (m_extError)
294           {
295             m_sink->Deinitialize();
296             delete m_sink;
297             m_sink = NULL;
298             m_state = S_TOP_CONFIGURED_SUSPEND;
299             m_extTimeout = 0;
300           }
301           else
302           {
303             m_state = S_TOP_CONFIGURED_PLAY;
304             m_extTimeout = delay / 2;
305             m_extSilenceTimer.Set(m_extSilenceTimeout);
306           }
307           return;
308         default:
309           break;
310         }
311       }
312       break;
313
314     case S_TOP_CONFIGURED_SUSPEND:
315       if (port == &m_controlPort)
316       {
317         switch (signal)
318         {
319         case CSinkControlProtocol::SILENCEMODE:
320           return;
321         case CSinkControlProtocol::VOLUME:
322           m_volume = *(float*)msg->data;
323           return;
324         default:
325           break;
326         }
327       }
328       else if (port == &m_dataPort)
329       {
330         switch (signal)
331         {
332         case CSinkDataProtocol::SAMPLE:
333           m_extError = false;
334           OpenSink();
335           OutputSamples(&m_sampleOfSilence);
336           m_state = S_TOP_CONFIGURED_PLAY;
337           m_extTimeout = 0;
338           m_bStateMachineSelfTrigger = true;
339           return;
340         case CSinkDataProtocol::DRAIN:
341           msg->Reply(CSinkDataProtocol::ACC);
342           return;
343         default:
344           break;
345         }
346       }
347       else if (port == NULL) // timeout
348       {
349         switch (signal)
350         {
351         case CSinkControlProtocol::TIMEOUT:
352           m_extTimeout = 10000;
353           return;
354         default:
355           break;
356         }
357       }
358       break;
359
360     case S_TOP_CONFIGURED_IDLE:
361       if (port == &m_dataPort)
362       {
363         switch (signal)
364         {
365         case CSinkDataProtocol::SAMPLE:
366           OutputSamples(&m_sampleOfSilence);
367           m_state = S_TOP_CONFIGURED_PLAY;
368           m_extTimeout = 0;
369           m_bStateMachineSelfTrigger = true;
370           return;
371         default:
372           break;
373         }
374       }
375       else if (port == NULL) // timeout
376       {
377         switch (signal)
378         {
379         case CSinkControlProtocol::TIMEOUT:
380           m_sink->Deinitialize();
381           delete m_sink;
382           m_sink = NULL;
383           m_state = S_TOP_CONFIGURED_SUSPEND;
384           m_extTimeout = 10000;
385           return;
386         default:
387           break;
388         }
389       }
390       break;
391
392     case S_TOP_CONFIGURED_PLAY:
393       if (port == NULL) // timeout
394       {
395         switch (signal)
396         {
397         case CSinkControlProtocol::TIMEOUT:
398           if (!m_extSilenceTimer.IsTimePast())
399           {
400             m_state = S_TOP_CONFIGURED_SILENCE;
401             m_extTimeout = 0;
402           }
403           else
404           {
405             m_sink->Drain();
406             m_state = S_TOP_CONFIGURED_IDLE;
407             m_extTimeout = 10000;
408           }
409           return;
410         default:
411           break;
412         }
413       }
414       break;
415
416     case S_TOP_CONFIGURED_SILENCE:
417       if (port == NULL) // timeout
418       {
419         switch (signal)
420         {
421         case CSinkControlProtocol::TIMEOUT:
422           OutputSamples(&m_sampleOfSilence);
423           if (m_extError)
424           {
425             m_sink->Deinitialize();
426             delete m_sink;
427             m_sink = NULL;
428             m_state = S_TOP_CONFIGURED_SUSPEND;
429           }
430           else
431             m_state = S_TOP_CONFIGURED_PLAY;
432           m_extTimeout = 0;
433           return;
434         default:
435           break;
436         }
437       }
438       break;
439
440     default: // we are in no state, should not happen
441       CLog::Log(LOGERROR, "CActiveAESink::%s - no valid state: %d", __FUNCTION__, m_state);
442       return;
443     }
444   } // for
445 }
446
447 void CActiveAESink::Process()
448 {
449   Message *msg = NULL;
450   Protocol *port = NULL;
451   bool gotMsg;
452   XbmcThreads::EndTime timer;
453
454   m_state = S_TOP_UNCONFIGURED;
455   m_extTimeout = 1000;
456   m_bStateMachineSelfTrigger = false;
457
458   while (!m_bStop)
459   {
460     gotMsg = false;
461     timer.Set(m_extTimeout);
462
463     if (m_bStateMachineSelfTrigger)
464     {
465       m_bStateMachineSelfTrigger = false;
466       // self trigger state machine
467       StateMachine(msg->signal, port, msg);
468       if (!m_bStateMachineSelfTrigger)
469       {
470         msg->Release();
471         msg = NULL;
472       }
473       continue;
474     }
475     // check control port
476     else if (m_controlPort.ReceiveOutMessage(&msg))
477     {
478       gotMsg = true;
479       port = &m_controlPort;
480     }
481     // check data port
482     else if (m_dataPort.ReceiveOutMessage(&msg))
483     {
484       gotMsg = true;
485       port = &m_dataPort;
486     }
487
488     if (gotMsg)
489     {
490       StateMachine(msg->signal, port, msg);
491       if (!m_bStateMachineSelfTrigger)
492       {
493         msg->Release();
494         msg = NULL;
495       }
496       continue;
497     }
498
499     // wait for message
500     else if (m_outMsgEvent.WaitMSec(m_extTimeout))
501     {
502       m_extTimeout = timer.MillisLeft();
503       continue;
504     }
505     // time out
506     else
507     {
508       msg = m_controlPort.GetMessage();
509       msg->signal = CSinkControlProtocol::TIMEOUT;
510       port = 0;
511       // signal timeout to state machine
512       StateMachine(msg->signal, port, msg);
513       if (!m_bStateMachineSelfTrigger)
514       {
515         msg->Release();
516         msg = NULL;
517       }
518     }
519   }
520 }
521
522 void CActiveAESink::EnumerateSinkList(bool force)
523 {
524   if (!m_sinkInfoList.empty() && !force)
525     return;
526
527   unsigned int c_retry = 5;
528   m_sinkInfoList.clear();
529   CAESinkFactory::EnumerateEx(m_sinkInfoList);
530   while(m_sinkInfoList.size() == 0 && c_retry > 0)
531   {
532     CLog::Log(LOGNOTICE, "No Devices found - retry: %d", c_retry);
533     Sleep(2000);
534     c_retry--;
535     // retry the enumeration
536     CAESinkFactory::EnumerateEx(m_sinkInfoList, true);
537   }
538   CLog::Log(LOGNOTICE, "Found %lu Lists of Devices", m_sinkInfoList.size());
539   PrintSinks();
540 }
541
542 void CActiveAESink::PrintSinks()
543 {
544   for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
545   {
546     CLog::Log(LOGNOTICE, "Enumerated %s devices:", itt->m_sinkName.c_str());
547     int count = 0;
548     for (AEDeviceInfoList::iterator itt2 = itt->m_deviceInfoList.begin(); itt2 != itt->m_deviceInfoList.end(); ++itt2)
549     {
550       CLog::Log(LOGNOTICE, "    Device %d", ++count);
551       CAEDeviceInfo& info = *itt2;
552       std::stringstream ss((std::string)info);
553       std::string line;
554       while(std::getline(ss, line, '\n'))
555         CLog::Log(LOGNOTICE, "        %s", line.c_str());
556     }
557   }
558 }
559
560 void CActiveAESink::EnumerateOutputDevices(AEDeviceList &devices, bool passthrough)
561 {
562   EnumerateSinkList(false);
563
564   for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
565   {
566     AESinkInfo sinkInfo = *itt;
567     for (AEDeviceInfoList::iterator itt2 = sinkInfo.m_deviceInfoList.begin(); itt2 != sinkInfo.m_deviceInfoList.end(); ++itt2)
568     {
569       CAEDeviceInfo devInfo = *itt2;
570       if (passthrough && devInfo.m_deviceType == AE_DEVTYPE_PCM)
571         continue;
572
573       std::string device = sinkInfo.m_sinkName + ":" + devInfo.m_deviceName;
574
575       std::stringstream ss;
576
577       /* add the sink name if we have more then one sink type */
578       if (m_sinkInfoList.size() > 1)
579         ss << sinkInfo.m_sinkName << ": ";
580
581       ss << devInfo.m_displayName;
582       if (!devInfo.m_displayNameExtra.empty())
583         ss << ", " << devInfo.m_displayNameExtra;
584
585       devices.push_back(AEDevice(ss.str(), device));
586     }
587   }
588 }
589
590 std::string CActiveAESink::GetDefaultDevice(bool passthrough)
591 {
592   EnumerateSinkList(false);
593
594   for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
595   {
596     AESinkInfo sinkInfo = *itt;
597     for (AEDeviceInfoList::iterator itt2 = sinkInfo.m_deviceInfoList.begin(); itt2 != sinkInfo.m_deviceInfoList.end(); ++itt2)
598     {
599       CAEDeviceInfo devInfo = *itt2;
600       if (passthrough && devInfo.m_deviceType == AE_DEVTYPE_PCM)
601         continue;
602
603       std::string device = sinkInfo.m_sinkName + ":" + devInfo.m_deviceName;
604       return device;
605     }
606   }
607   return "default";
608 }
609
610 void CActiveAESink::GetDeviceFriendlyName(std::string &device)
611 {
612   m_deviceFriendlyName = "Device not found";
613   /* Match the device and find its friendly name */
614   for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
615   {
616     AESinkInfo sinkInfo = *itt;
617     for (AEDeviceInfoList::iterator itt2 = sinkInfo.m_deviceInfoList.begin(); itt2 != sinkInfo.m_deviceInfoList.end(); ++itt2)
618     {
619       CAEDeviceInfo& devInfo = *itt2;
620       if (devInfo.m_deviceName == device)
621       {
622         m_deviceFriendlyName = devInfo.m_displayName;
623         break;
624       }
625     }
626   }
627   return;
628 }
629
630 void CActiveAESink::OpenSink()
631 {
632   // we need a copy of m_device here because ParseDevice and CreateDevice write back
633   // into this variable
634   std::string device = m_device;
635   std::string driver;
636   bool passthrough = AE_IS_RAW(m_requestedFormat.m_dataFormat);
637
638   CAESinkFactory::ParseDevice(device, driver);
639   if (driver.empty() && m_sink)
640     driver = m_sink->GetName();
641
642   CLog::Log(LOGINFO, "CActiveAESink::OpenSink - initialize sink");
643
644   if (m_sink)
645   {
646     m_sink->Drain();
647     m_sink->Deinitialize();
648     delete m_sink;
649     m_sink = NULL;
650   }
651
652   // get the display name of the device
653   GetDeviceFriendlyName(device);
654
655   // if we already have a driver, prepend it to the device string
656   if (!driver.empty())
657     device = driver + ":" + device;
658
659   // WARNING: this changes format and does not use passthrough
660   m_sinkFormat = m_requestedFormat;
661   CLog::Log(LOGDEBUG, "CActiveAESink::OpenSink - trying to open device %s", device.c_str());
662   m_sink = CAESinkFactory::Create(device, m_sinkFormat, passthrough);
663
664   if (!m_sink)
665   {
666     CLog::Log(LOGERROR, "CActiveAESink::OpenSink - no sink was returned");
667     m_extError = true;
668     return;
669   }
670
671   m_sink->SetVolume(m_volume);
672
673 #ifdef WORDS_BIGENDIAN
674   if (m_sinkFormat.m_dataFormat == AE_FMT_S16BE)
675     m_sinkFormat.m_dataFormat = AE_FMT_S16NE;
676   else if (m_sinkFormat.m_dataFormat == AE_FMT_S32BE)
677     m_sinkFormat.m_dataFormat = AE_FMT_S32NE;
678 #else
679   if (m_sinkFormat.m_dataFormat == AE_FMT_S16LE)
680     m_sinkFormat.m_dataFormat = AE_FMT_S16NE;
681   else if (m_sinkFormat.m_dataFormat == AE_FMT_S32LE)
682     m_sinkFormat.m_dataFormat = AE_FMT_S32NE;
683 #endif
684
685   CLog::Log(LOGDEBUG, "CActiveAESink::OpenSink - %s Initialized:", m_sink->GetName());
686   CLog::Log(LOGDEBUG, "  Output Device : %s", m_deviceFriendlyName.c_str());
687   CLog::Log(LOGDEBUG, "  Sample Rate   : %d", m_sinkFormat.m_sampleRate);
688   CLog::Log(LOGDEBUG, "  Sample Format : %s", CAEUtil::DataFormatToStr(m_sinkFormat.m_dataFormat));
689   CLog::Log(LOGDEBUG, "  Channel Count : %d", m_sinkFormat.m_channelLayout.Count());
690   CLog::Log(LOGDEBUG, "  Channel Layout: %s", ((std::string)m_sinkFormat.m_channelLayout).c_str());
691   CLog::Log(LOGDEBUG, "  Frames        : %d", m_sinkFormat.m_frames);
692   CLog::Log(LOGDEBUG, "  Frame Samples : %d", m_sinkFormat.m_frameSamples);
693   CLog::Log(LOGDEBUG, "  Frame Size    : %d", m_sinkFormat.m_frameSize);
694
695   // init sample of silence
696   SampleConfig config;
697   config.fmt = CActiveAEResample::GetAVSampleFormat(m_sinkFormat.m_dataFormat);
698   config.bits_per_sample = CAEUtil::DataFormatToUsedBits(m_sinkFormat.m_dataFormat);
699   config.channel_layout = CActiveAEResample::GetAVChannelLayout(m_sinkFormat.m_channelLayout);
700   config.channels = m_sinkFormat.m_channelLayout.Count();
701   config.sample_rate = m_sinkFormat.m_sampleRate;
702
703   // init sample of silence/noise
704   delete m_sampleOfSilence.pkt;
705   m_sampleOfSilence.pkt = new CSoundPacket(config, m_sinkFormat.m_frames);
706   m_sampleOfSilence.pkt->nb_samples = m_sampleOfSilence.pkt->max_nb_samples;
707   if (!passthrough)
708     GenerateNoise();
709
710   if (m_convertBuffer)
711   {
712     _aligned_free(m_convertBuffer);
713     m_convertBuffer = NULL;
714   }
715   m_convertFn = NULL;
716   m_convertState = CHECK_CONVERT;
717 }
718
719 void CActiveAESink::ReturnBuffers()
720 {
721   Message *msg = NULL;
722   CSampleBuffer *samples;
723   while (m_dataPort.ReceiveOutMessage(&msg))
724   {
725     if (msg->signal == CSinkDataProtocol::SAMPLE)
726     {
727       samples = *((CSampleBuffer**)msg->data);
728       msg->Reply(CSinkDataProtocol::RETURNSAMPLE, &samples, sizeof(CSampleBuffer*));
729     }
730   }
731 }
732
733 unsigned int CActiveAESink::OutputSamples(CSampleBuffer* samples)
734 {
735   uint8_t *buffer = samples->pkt->data[0];
736   unsigned int frames = samples->pkt->nb_samples;
737   unsigned int maxFrames;
738   int retry = 0;
739   unsigned int written = 0;
740   double sinkDelay = 0.0;
741
742   switch(m_convertState)
743   {
744   case SKIP_CONVERT:
745     break;
746   case NEED_CONVERT:
747     EnsureConvertBuffer(samples);
748     buffer = Convert(samples);
749     break;
750   case NEED_BYTESWAP:
751     Endian_Swap16_buf((uint16_t *)buffer, (uint16_t *)buffer, frames * samples->pkt->config.channels);
752     break;
753   case CHECK_CONVERT:
754     ConvertInit(samples);
755     if (m_convertState == NEED_CONVERT)
756       buffer = Convert(samples);
757     else if (m_convertState == NEED_BYTESWAP)
758       Endian_Swap16_buf((uint16_t *)buffer, (uint16_t *)buffer, frames * samples->pkt->config.channels);
759     break;
760   default:
761     break;
762   }
763
764   while(frames > 0)
765   {
766     maxFrames = std::min(frames, m_sinkFormat.m_frames);
767     written = m_sink->AddPackets(buffer, maxFrames, true, true);
768     if (written == 0)
769     {
770       Sleep(500*m_sinkFormat.m_frames/m_sinkFormat.m_sampleRate);
771       retry++;
772       if (retry > 4)
773       {
774         m_extError = true;
775         CLog::Log(LOGERROR, "CActiveAESink::OutputSamples - failed");
776         m_stats->UpdateSinkDelay(0, frames);
777         return 0;
778       }
779       else
780         continue;
781     }
782     else if (written > maxFrames)
783     {
784       m_extError = true;
785       CLog::Log(LOGERROR, "CActiveAESink::OutputSamples - sink returned error");
786       m_stats->UpdateSinkDelay(0, samples->pool ? maxFrames : 0);
787       return 0;
788     }
789     frames -= written;
790     buffer += written*m_sinkFormat.m_frameSize;
791     sinkDelay = m_sink->GetDelay();
792     m_stats->UpdateSinkDelay(sinkDelay, samples->pool ? written : 0);
793   }
794   return sinkDelay*1000;
795 }
796
797 void CActiveAESink::ConvertInit(CSampleBuffer* samples)
798 {
799   if (CActiveAEResample::GetAESampleFormat(samples->pkt->config.fmt, samples->pkt->config.bits_per_sample) != m_sinkFormat.m_dataFormat)
800   {
801     m_convertFn = CAEConvert::FrFloat(m_sinkFormat.m_dataFormat);
802     if (m_convertBuffer)
803       _aligned_free(m_convertBuffer);
804     m_convertBufferSampleSize = samples->pkt->max_nb_samples;
805     m_convertBuffer = (uint8_t*)_aligned_malloc(samples->pkt->max_nb_samples * m_sinkFormat.m_channelLayout.Count() * m_sinkFormat.m_frameSize, 16);
806     memset(m_convertBuffer, 0, samples->pkt->max_nb_samples * m_sinkFormat.m_channelLayout.Count() * m_sinkFormat.m_frameSize);
807     m_convertState = NEED_CONVERT;
808   }
809   else if (AE_IS_RAW(m_requestedFormat.m_dataFormat) && CAEUtil::S16NeedsByteSwap(AE_FMT_S16NE, m_sinkFormat.m_dataFormat))
810   {
811     m_convertState = NEED_BYTESWAP;
812   }
813   else
814     m_convertState = SKIP_CONVERT;
815 }
816
817 void CActiveAESink::EnsureConvertBuffer(CSampleBuffer* samples)
818 {
819   if (!m_convertBuffer)
820     return;
821
822   if (samples->pkt->max_nb_samples <= m_convertBufferSampleSize)
823     return;
824
825   _aligned_free(m_convertBuffer);
826   m_convertBufferSampleSize = samples->pkt->max_nb_samples;
827   m_convertBuffer = (uint8_t*)_aligned_malloc(samples->pkt->max_nb_samples * m_sinkFormat.m_channelLayout.Count() * m_sinkFormat.m_frameSize, 16);
828   memset(m_convertBuffer, 0, samples->pkt->max_nb_samples * m_sinkFormat.m_channelLayout.Count() * m_sinkFormat.m_frameSize);
829 }
830
831 uint8_t* CActiveAESink::Convert(CSampleBuffer* samples)
832 {
833   m_convertFn((float*)samples->pkt->data[0], samples->pkt->nb_samples * samples->pkt->config.channels, m_convertBuffer);
834   return m_convertBuffer;
835 }
836
837 #define PI 3.1415926536f
838
839 void CActiveAESink::GenerateNoise()
840 {
841   int nb_floats = m_sinkFormat.m_frames*m_sinkFormat.m_channelLayout.Count();
842   float *noise = (float*)_aligned_malloc(nb_floats*sizeof(float), 16);
843
844   float R1, R2;
845   for(int i=0; i<nb_floats;i++)
846   {
847     do
848     {
849       R1 = (float) rand() / (float) RAND_MAX;
850       R2 = (float) rand() / (float) RAND_MAX;
851     }
852     while(R1 == 0.0f);
853     
854     noise[i] = (float) sqrt( -2.0f * log( R1 )) * cos( 2.0f * PI * R2 ) * 0.00001f;
855   }
856
857   AEDataFormat fmt = CActiveAEResample::GetAESampleFormat(m_sampleOfSilence.pkt->config.fmt, m_sampleOfSilence.pkt->config.bits_per_sample);
858   CAEConvert::AEConvertFrFn convertFn = CAEConvert::FrFloat(fmt);
859   convertFn(noise, nb_floats, m_sampleOfSilence.pkt->data[0]);
860   _aligned_free(noise);
861 }