/////////////////////////////////////////////////////////////////////
//  RAWOutput.cpp
/////////////////////////////////////////////////////////////////////
//
//  Description: Writes a 16bit stereo RAW file with the output song
//               data
//
//  This file is part of the SkalePlayer library.
//
//  This library is freeware only for non-commercial projects. For 
//  commercial uses of this library you must to get my permision,
//  contact me at baktery@skale.org
//
//  Use it at your own risk.
//
//  Ruben Ramos Salvador aka Baktery/Chanka
//  email: baktery@skale.org
//  http://www.skale.org
//
/////////////////////////////////////////////////////////////////////

// Includes
#include <windows.h>
#include <stdio.h>

// SkalePlayer Includes
#include "SkalePlayer.h"

// FileName
char g_szSongFileName[1024] = { 0 };

// Title
const char TITLE[] = "RAWOutput Example";


////////////////////////////////////////////////
// GetFileName(): Gets the filename to play
////////////////////////////////////////////////
bool GetFileName(HINSTANCE hInstance)
{
  bool bOK = true;

  OPENFILENAME OpenFileName;
  memset(&OpenFileName,0,sizeof(OpenFileName));
  OpenFileName.lStructSize = sizeof(OpenFileName);
  OpenFileName.hInstance = hInstance; 
  OpenFileName.lpstrFilter = "SkalePlayer Supported Formats(*.MOD *.XM *.SKM)\0*.mod;*.xm;*.skm\0All Files(*.*)\0*.*\0";
  OpenFileName.lpstrFile = g_szSongFileName; 
  OpenFileName.nMaxFile = sizeof(g_szSongFileName); 
  OpenFileName.lpstrTitle = TITLE; 
  OpenFileName.Flags = OFN_FILEMUSTEXIST; 

  bOK = GetOpenFileName(&OpenFileName) != 0;    

  return bOK;
}

////////////////////////////////////////////////
// EventHandler (to detect end of song)
////////////////////////////////////////////////
class CSkalePlayerEvent : public ISkalePlayer::IEventHandler
{
public:
  CSkalePlayerEvent () : m_bEnd(false)  {}

  void    Event   (EEvent eEvent, const TEventInfo* pEventInfo)
  {
    if ( eEvent == ISkalePlayer::IEventHandler::EVENT_ENDOFSONG )
    {
      m_bEnd = true;
      // Stop the song
      ISkalePlayer::GetSkalePlayer()->SetPlayMode(ISkalePlayer::PLAY_MODE_STOP_PLAYBACK);
    }
  }
  bool    IsEnd   () const { return m_bEnd; }

private:
  bool    m_bEnd;
};


////////////////////////////////////////////////
// WriteOutputToRAWFile(): 
////////////////////////////////////////////////
void WriteOutputToRAWFile(const CSkalePlayerEvent* pEvent)
{
  // Open dest RAW file
  FILE* f = fopen("RAWOutput.raw","wb");

  if ( f )
  {
    // Output buffer
    const int BUFFER_SAMPLES_SIZE = 44100;
    float afBuffer[BUFFER_SAMPLES_SIZE*2];

    // Process and save data until the end of the song
    while ( !pEvent->IsEnd() )
    {
      ISkalePlayer::GetSkalePlayer()->SlaveProcess(afBuffer,BUFFER_SAMPLES_SIZE);

      // Convert to 16bit
      short asBuffer[BUFFER_SAMPLES_SIZE*2];
      for ( int j = 0 ; j < BUFFER_SAMPLES_SIZE*2 ; ++j )
        asBuffer[j] = (short)(afBuffer[j]*32767.f);

      // Save 16bit data to RAW file
      fwrite(asBuffer,BUFFER_SAMPLES_SIZE*2,sizeof(short),f);
    }

    // Close RAW File
    fclose(f);
  }
}



////////////////////////////////////////////////
// WinMain()
////////////////////////////////////////////////
int __stdcall WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
  if ( GetFileName(hInstance) )
  {
    // Must init with Slave Mode
    ISkalePlayer::TInitData InitData;
    InitData.m_eMode = ISkalePlayer::INIT_MODE_SLAVE;

    // Init Skale Player
    ISkalePlayer* pSkalePlayer = ISkalePlayer::GetSkalePlayer();
    ISkalePlayer::EInitError Error = pSkalePlayer->Init(InitData);

    if ( Error == ISkalePlayer::INIT_OK )
    {
      // Setup our Event Handler
      CSkalePlayerEvent Event;
      pSkalePlayer->SetEventHandler(&Event);

      // Load Song
      const ISkalePlayer::ISong* pSong = pSkalePlayer->LoadSongFromFile(g_szSongFileName);

      if ( pSong )
      {
        // Set loaded song as active
        pSkalePlayer->SetCurrentSong(pSong);

        // Play
        pSkalePlayer->SetPlayMode(ISkalePlayer::PLAY_MODE_PLAY_SONG_FROM_START);

        // Write output to RAW file
        WriteOutputToRAWFile(&Event);
      }

      // Uninit SkalePlayer
      pSkalePlayer->End();
    }
  }

  return 0;
}

