PageRenderTime 35ms CodeModel.GetById 11ms app.highlight 21ms RepoModel.GetById 1ms app.codeStats 0ms

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