#pragma once
#ifndef V2MPLAYER_H_
#define V2MPLAYER_H_
#include <stdint.h>
#include <string.h>
#include "types.h"
class V2MPlayer
{
public:
void Init(uint32_t a_tickspersec=1000) { m_tpc=a_tickspersec; memset(&m_base, 0, sizeof(V2MBase)); }
bool Open(const void *a_v2mptr, uint32_t a_samplerate=44100);
void Close();
void Play(uint32_t a_time=0);
void Stop(uint32_t a_fadetime=0);
void Render(float *a_buffer, uint32_t a_len, bool a_add=0);
static void RenderProxy(void *a_this, float *a_buffer, uint32_t a_len)
{
reinterpret_cast<V2MPlayer*>(a_this)->Render(a_buffer, a_len);
}
bool NoEnd();
uint32_t Length();
bool IsPlaying();
#ifdef V2MPLAYER_SYNC_FUNCTIONS
uint32_t CalcPositions(int32_t **a_dest);
#endif
private:
struct V2MBase
{
bool valid;
const uint8_t *patchmap;
const uint8_t *globals;
uint32_t timediv;
uint32_t timediv2;
uint32_t maxtime;
const uint8_t *gptr;
uint32_t gdnum;
struct Channel
{
uint32_t notenum;
const uint8_t *noteptr;
uint32_t pcnum;
const uint8_t *pcptr;
uint32_t pbnum;
const uint8_t *pbptr;
struct CC {
uint32_t ccnum;
const uint8_t *ccptr;
} ctl[7];
} chan[16];
const char *speechdata;
const char *speechptrs[256];
};
struct PlayerState
{
enum { OFF, STOPPED, PLAYING, } state;
uint32_t time;
uint32_t nexttime;
const uint8_t *gptr;
uint32_t gnt;
uint32_t gnr;
uint32_t usecs;
uint32_t num;
uint32_t den;
uint32_t tpq;
uint32_t bar;
uint32_t beat;
uint32_t tick;
struct Channel
{
const uint8_t *noteptr;
uint32_t notenr;
uint32_t notent;
uint8_t lastnte;
uint8_t lastvel;
const uint8_t *pcptr;
uint32_t pcnr;
uint32_t pcnt;
uint8_t lastpc;
const uint8_t *pbptr;
uint32_t pbnr;
uint32_t pbnt;
uint8_t lastpb0;
uint8_t lastpb1;
struct CC
{
const uint8_t *ccptr;
uint32_t ccnt;
uint32_t ccnr;
uint8_t lastcc;
} ctl[7];
} chan[16];
uint32_t cursmpl;
uint32_t smpldelta;
uint32_t smplrem;
uint32_t tdif;
};
uint8_t m_synth[3*1024*1024];
uint32_t m_tpc;
V2MBase m_base;
PlayerState m_state;
uint32_t m_samplerate;
int32_t m_timeoffset;
uint8_t m_midibuf[4096];
float m_fadeval;
float m_fadedelta;
bool InitBase(const void *a_v2m); void Reset(); void Tick(); };
#endif