/xbmc/cores/paplayer/NSFCodec.cpp

http://github.com/xbmc/xbmc · C++ · 156 lines · 112 code · 21 blank · 23 comment · 12 complexity · b273cfd4e46792730249f3a9a5105ab9 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 "NSFCodec.h"
  21. #include "utils/log.h"
  22. #include "utils/RegExp.h"
  23. #include "utils/URIUtils.h"
  24. NSFCodec::NSFCodec()
  25. {
  26. m_iTrack = 0;
  27. m_CodecName = "nsf";
  28. m_nsf = NULL;
  29. m_bIsPlaying = false;
  30. m_szBuffer = NULL;
  31. m_szStartOfBuffer = NULL;
  32. m_iDataInBuffer = 0;
  33. m_iDataPos = 0;
  34. }
  35. NSFCodec::~NSFCodec()
  36. {
  37. DeInit();
  38. }
  39. bool NSFCodec::Init(const CStdString &strFile, unsigned int filecache)
  40. {
  41. DeInit();
  42. if (!m_dll.Load())
  43. return false; // error logged previously
  44. CStdString strFileToLoad = strFile;
  45. m_iTrack = 0;
  46. if (URIUtils::HasExtension(strFile, ".nsfstream"))
  47. {
  48. // Extract the track to play
  49. CStdString strFileName=URIUtils::GetFileName(strFile);
  50. int iStart=strFileName.ReverseFind('-')+1;
  51. m_iTrack = atoi(strFileName.substr(iStart, strFileName.size()-iStart-10).c_str());
  52. // The directory we are in, is the file
  53. // that contains the bitstream to play,
  54. // so extract it
  55. strFileToLoad = URIUtils::GetDirectory(strFile);
  56. URIUtils::RemoveSlashAtEnd(strFileToLoad); // we want the filename
  57. }
  58. m_nsf = m_dll.LoadNSF(strFileToLoad.c_str());
  59. if (!m_nsf)
  60. {
  61. CLog::Log(LOGERROR,"NSFCodec: error opening file %s!",strFile.c_str());
  62. return false;
  63. }
  64. m_Channels = 1;
  65. m_SampleRate = 48000;
  66. m_BitsPerSample = 16;
  67. m_DataFormat = AE_FMT_S16NE;
  68. m_TotalTime = 4*60*1000; // fixme?
  69. m_iDataPos = 0;
  70. return true;
  71. }
  72. void NSFCodec::DeInit()
  73. {
  74. if (m_nsf)
  75. m_dll.FreeNSF(m_nsf);
  76. m_nsf = 0;
  77. m_bIsPlaying = false;
  78. if (m_szBuffer)
  79. delete[] m_szBuffer;
  80. m_szBuffer = NULL;
  81. }
  82. int64_t NSFCodec::Seek(int64_t iSeekTime)
  83. {
  84. if (m_iDataPos > iSeekTime/1000*48000*2)
  85. {
  86. m_dll.StartPlayback(m_nsf,m_iTrack);
  87. m_iDataPos = 0;
  88. }
  89. while (m_iDataPos+2*48000/m_dll.GetPlaybackRate(m_nsf)*2 < iSeekTime/1000*48000*2)
  90. {
  91. m_dll.FrameAdvance(m_nsf);
  92. m_iDataInBuffer = 48000/m_dll.GetPlaybackRate(m_nsf)*2;
  93. m_szStartOfBuffer = m_szBuffer;
  94. m_iDataPos += 48000/m_dll.GetPlaybackRate(m_nsf)*2;
  95. }
  96. m_dll.FillBuffer(m_nsf,m_szBuffer,48000/m_dll.GetPlaybackRate(m_nsf)); // *2 since two channels
  97. if (iSeekTime/1000*48000*2 > 48000/m_dll.GetPlaybackRate(m_nsf)*2)
  98. m_iDataPos += 48000/m_dll.GetPlaybackRate(m_nsf)*2;
  99. else
  100. m_iDataPos = 0;
  101. m_iDataInBuffer -= int(iSeekTime/1000*48000*2-m_iDataPos);
  102. m_szStartOfBuffer += (iSeekTime/1000*48000*2-m_iDataPos);
  103. m_iDataPos = iSeekTime/1000*48000*2;
  104. return iSeekTime;
  105. }
  106. int NSFCodec::ReadPCM(BYTE *pBuffer, int size, int *actualsize)
  107. {
  108. if (!m_nsf)
  109. return READ_ERROR;
  110. if (m_iDataPos >= m_TotalTime/1000*48000*2)
  111. return READ_EOF;
  112. if (!m_bIsPlaying)
  113. {
  114. m_dll.StartPlayback(m_nsf,m_iTrack);
  115. m_bIsPlaying = true;
  116. m_szBuffer = new char[48000/m_dll.GetPlaybackRate(m_nsf)*2];
  117. m_szStartOfBuffer = m_szBuffer;
  118. m_iDataPos = 0;
  119. }
  120. if (m_iDataInBuffer <= 0)
  121. {
  122. m_iDataInBuffer = m_dll.FillBuffer(m_nsf,m_szBuffer,48000/m_dll.GetPlaybackRate(m_nsf)); // *2 since two channels
  123. m_szStartOfBuffer = m_szBuffer;
  124. }
  125. *actualsize = size<m_iDataInBuffer?size:m_iDataInBuffer;
  126. memcpy(pBuffer,m_szStartOfBuffer,*actualsize);
  127. m_szStartOfBuffer += *actualsize;
  128. m_iDataInBuffer -= *actualsize;
  129. m_iDataPos += *actualsize;
  130. return READ_SUCCESS;
  131. }
  132. bool NSFCodec::CanInit()
  133. {
  134. return m_dll.CanLoad();
  135. }