/xbmc/cores/paplayer/SIDCodec.cpp

http://github.com/xbmc/xbmc · C++ · 153 lines · 108 code · 22 blank · 23 comment · 16 complexity · 78b0a97f2a9c2a6ef279561b3995ff6d MD5 · raw file

  1. /*
  2. * Copyright (C) 2005-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. #include "SIDCodec.h"
  21. #include "cores/DllLoader/DllLoader.h"
  22. #include "FileItem.h"
  23. #include "utils/log.h"
  24. #include "utils/URIUtils.h"
  25. #include "cores/AudioEngine/Utils/AEUtil.h"
  26. SIDCodec::SIDCodec()
  27. {
  28. m_CodecName = "sid";
  29. m_sid = 0;
  30. m_iTrack = -1;
  31. m_iDataPos = -1;
  32. }
  33. SIDCodec::~SIDCodec()
  34. {
  35. DeInit();
  36. }
  37. bool SIDCodec::Init(const CStdString &strFile, unsigned int filecache)
  38. {
  39. if (!m_dll.Load())
  40. return false; // error logged previously
  41. m_dll.Init();
  42. CStdString strFileToLoad = strFile;
  43. m_iTrack = 0;
  44. if (URIUtils::HasExtension(strFile, ".sidstream"))
  45. {
  46. // Extract the track to play
  47. CStdString strFileName=URIUtils::GetFileName(strFile);
  48. int iStart=strFileName.ReverseFind('-')+1;
  49. m_iTrack = atoi(strFileName.substr(iStart, strFileName.size()-iStart-10).c_str());
  50. // The directory we are in, is the file
  51. // that contains the bitstream to play,
  52. // so extract it
  53. strFileToLoad = URIUtils::GetDirectory(strFile);
  54. URIUtils::RemoveSlashAtEnd(strFileToLoad); // we want the filename
  55. }
  56. m_sid = m_dll.LoadSID(strFileToLoad.c_str());
  57. if (!m_sid)
  58. {
  59. CLog::Log(LOGERROR,"SIDCodec: error opening file %s!",strFile.c_str());
  60. return false;
  61. }
  62. m_Channels = 1;
  63. m_SampleRate = 48000;
  64. m_BitsPerSample = 16;
  65. m_TotalTime = 4*60*1000;
  66. m_DataFormat = AE_FMT_S16NE;
  67. return true;
  68. }
  69. void SIDCodec::DeInit()
  70. {
  71. if (m_sid)
  72. m_dll.FreeSID(m_sid);
  73. m_sid = 0;
  74. }
  75. int64_t SIDCodec::Seek(int64_t iSeekTime)
  76. {
  77. char temp[3840*2];
  78. if (m_iDataPos > iSeekTime/1000*48000*2)
  79. {
  80. m_dll.StartPlayback(m_sid,m_iTrack);
  81. m_iDataPos = 0;
  82. }
  83. while (m_iDataPos < iSeekTime/1000*48000*2)
  84. {
  85. int64_t iRead = iSeekTime/1000*48000*2-m_iDataPos;
  86. if (iRead > 3840*2)
  87. {
  88. m_dll.SetSpeed(m_sid,32*100);
  89. iRead = 3840*2;
  90. }
  91. else
  92. m_dll.SetSpeed(m_sid,100);
  93. iRead = m_dll.FillBuffer(m_sid,temp,int(iRead));
  94. if (!iRead)
  95. break; // get out of here
  96. if (iRead == 3840*2)
  97. m_iDataPos += iRead*32;
  98. else m_iDataPos += iRead;
  99. }
  100. return iSeekTime;
  101. }
  102. int SIDCodec::ReadPCM(BYTE *pBuffer, int size, int *actualsize)
  103. {
  104. if (m_iDataPos == -1)
  105. {
  106. m_dll.StartPlayback(m_sid,m_iTrack);
  107. m_iDataPos = 0;
  108. }
  109. if (m_iDataPos >= m_TotalTime/1000*48000*2)
  110. return READ_EOF;
  111. m_dll.SetSpeed(m_sid,100);
  112. if ((*actualsize=m_dll.FillBuffer(m_sid,pBuffer,size))> 0)
  113. {
  114. m_iDataPos += *actualsize;
  115. return READ_SUCCESS;
  116. }
  117. return READ_ERROR;
  118. }
  119. bool SIDCodec::CanInit()
  120. {
  121. return m_dll.CanLoad();
  122. }
  123. CAEChannelInfo SIDCodec::GetChannelInfo()
  124. {
  125. static enum AEChannel map[1][2] = {
  126. {AE_CH_FC, AE_CH_NULL}
  127. };
  128. if (m_Channels > 1)
  129. return CAEUtil::GuessChLayout(m_Channels);
  130. return CAEChannelInfo(map[m_Channels - 1]);
  131. }