#include <cstdint>
#include "./pxtn.h"
#include "./pxtnService.h"
#define _VERSIONSIZE 16
#define _CODESIZE 8
static const char* _code_tune_x2x = "PTTUNE--20050608";
static const char* _code_tune_x3x = "PTTUNE--20060115";
static const char* _code_tune_x4x = "PTTUNE--20060930";
static const char* _code_tune_v5 = "PTTUNE--20071119";
static const char* _code_proj_x1x = "PTCOLLAGE-050227";
static const char* _code_proj_x2x = "PTCOLLAGE-050608";
static const char* _code_proj_x3x = "PTCOLLAGE-060115";
static const char* _code_proj_x4x = "PTCOLLAGE-060930";
static const char* _code_proj_v5 = "PTCOLLAGE-071119";
static const char* _code_x1x_PROJ = "PROJECT=";
static const char* _code_x1x_EVEN = "EVENT===";
static const char* _code_x1x_UNIT = "UNIT====";
static const char* _code_x1x_END = "END=====";
static const char* _code_x1x_PCM = "matePCM=";
static const char* _code_x3x_pxtnUNIT = "pxtnUNIT";
static const char* _code_x4x_evenMAST = "evenMAST";
static const char* _code_x4x_evenUNIT = "evenUNIT";
static const char* _code_antiOPER = "antiOPER";
static const char* _code_num_UNIT = "num UNIT";
static const char* _code_MasterV5 = "MasterV5";
static const char* _code_Event_V5 = "Event V5";
static const char* _code_matePCM = "matePCM ";
static const char* _code_matePTV = "matePTV ";
static const char* _code_matePTN = "matePTN ";
static const char* _code_mateOGGV = "mateOGGV";
static const char* _code_effeDELA = "effeDELA";
static const char* _code_effeOVER = "effeOVER";
static const char* _code_textNAME = "textNAME";
static const char* _code_textCOMM = "textCOMM";
static const char* _code_assiUNIT = "assiUNIT";
static const char* _code_assiWOIC = "assiWOIC";
static const char* _code_pxtoneND = "pxtoneND";
enum _enum_Tag
{
_TAG_Unknown = 0,
_TAG_antiOPER ,
_TAG_x1x_PROJ ,
_TAG_x1x_UNIT ,
_TAG_x1x_PCM ,
_TAG_x1x_EVEN ,
_TAG_x1x_END ,
_TAG_x3x_pxtnUNIT,
_TAG_x4x_evenMAST,
_TAG_x4x_evenUNIT,
_TAG_num_UNIT ,
_TAG_MasterV5 ,
_TAG_Event_V5 ,
_TAG_matePCM ,
_TAG_matePTV ,
_TAG_matePTN ,
_TAG_mateOGGV ,
_TAG_effeDELA ,
_TAG_effeOVER ,
_TAG_textNAME ,
_TAG_textCOMM ,
_TAG_assiUNIT ,
_TAG_assiWOIC ,
_TAG_pxtoneND
};
pxtnService::pxtnService()
{
_b_init = false;
_b_edit = false;
_b_fix_evels_num = false;
text = NULL;
master = NULL;
evels = NULL;
_delays = NULL; _delay_max = _delay_num = 0;
_ovdrvs = NULL; _ovdrv_max = _ovdrv_num = 0;
_woices = NULL; _woice_max = _woice_num = 0;
_units = NULL; _unit_max = _unit_num = 0;
_ptn_bldr = NULL;
_sampled_proc = NULL;
_sampled_user = NULL;
_moo_constructor();
}
bool pxtnService::_release()
{
if( !_b_init ) return false;
_b_init = false;
_moo_destructer();
SAFE_DELETE( text );
SAFE_DELETE( master );
SAFE_DELETE( evels );
SAFE_DELETE( _ptn_bldr );
if( _delays ){ for( int32_t i = 0; i < _delay_num; i++ ) SAFE_DELETE( _delays[ i ] ); free( _delays ); _delays = NULL; }
if( _ovdrvs ){ for( int32_t i = 0; i < _ovdrv_num; i++ ) SAFE_DELETE( _ovdrvs[ i ] ); free( _ovdrvs ); _ovdrvs = NULL; }
if( _woices ){ for( int32_t i = 0; i < _woice_num; i++ ) SAFE_DELETE( _woices[ i ] ); free( _woices ); _woices = NULL; }
if( _units ){ for( int32_t i = 0; i < _unit_num ; i++ ) SAFE_DELETE( _units [ i ] ); free( _units ); _units = NULL; }
return true;
}
pxtnService::~pxtnService()
{
_release();
}
pxtnERR pxtnService:: init (){ return _init( 0, false ); }
pxtnERR pxtnService:: init_collage( int32_t fix_evels_num ){ return _init( fix_evels_num, true ); }
pxtnERR pxtnService::_init( int32_t fix_evels_num, bool b_edit )
{
if( _b_init ) return pxtnERR_INIT;
pxtnERR res = pxtnERR_VOID;
int32_t byte_size = 0;
if( !( text = new pxtnText () ) ){ res = pxtnERR_INIT ; goto End; }
if( !( master = new pxtnMaster () ) ){ res = pxtnERR_INIT ; goto End; }
if( !( evels = new pxtnEvelist () ) ){ res = pxtnERR_INIT ; goto End; }
if( !( _ptn_bldr = new pxtnPulse_NoiseBuilder() ) ){ res = pxtnERR_INIT ; goto End; }
if( ! _ptn_bldr->Init() ){ res = pxtnERR_ptn_init; goto End; }
if( fix_evels_num )
{
_b_fix_evels_num = true;
if( !evels->Allocate( fix_evels_num ) ){ res = pxtnERR_memory; goto End; }
}
else
{
_b_fix_evels_num = false;
}
byte_size = sizeof(pxtnDelay*) * pxtnMAX_TUNEDELAYSTRUCT;
if( !( _delays = (pxtnDelay** )malloc( byte_size ) ) ){ res = pxtnERR_memory; goto End; }
memset( _delays, 0, byte_size );
_delay_max = pxtnMAX_TUNEDELAYSTRUCT;
byte_size = sizeof(pxtnOverDrive*) * pxtnMAX_TUNEOVERDRIVESTRUCT;
if( !( _ovdrvs = (pxtnOverDrive**)malloc( byte_size ) ) ){ res = pxtnERR_memory; goto End; }
memset( _ovdrvs, 0, byte_size );
_ovdrv_max = pxtnMAX_TUNEOVERDRIVESTRUCT;
byte_size = sizeof(pxtnWoice*) * pxtnMAX_TUNEWOICESTRUCT;
if( !( _woices = (pxtnWoice** )malloc( byte_size ) ) ){ res = pxtnERR_memory; goto End; }
memset( _woices, 0, byte_size );
_woice_max = pxtnMAX_TUNEWOICESTRUCT;
byte_size = sizeof(pxtnUnit*) * pxtnMAX_TUNEUNITSTRUCT;
if( !( _units = (pxtnUnit** )malloc( byte_size ) ) ){ res = pxtnERR_memory; goto End; }
memset( _units, 0, byte_size );
_unit_max = pxtnMAX_TUNEUNITSTRUCT;
_group_num = pxtnMAX_TUNEGROUPNUM ;
if( !_moo_init() ){ res = pxtnERR_moo_init; goto End; }
if( fix_evels_num ) _moo_b_valid_data = true;
_b_edit = b_edit;
res = pxtnOK;
_b_init = true ;
End:
if( !_b_init ) _release();
return res;
}
bool pxtnService::AdjustMeasNum()
{
if( !_b_init ) return false;
master->AdjustMeasNum( evels->get_Max_Clock() );
return true;
}
int32_t pxtnService::Group_Num() const{ return _b_init ? _group_num : 0; }
pxtnERR pxtnService::tones_ready()
{
if( !_b_init ) return pxtnERR_INIT;
pxtnERR res = pxtnERR_VOID;
int32_t beat_num = master->get_beat_num ();
float beat_tempo = master->get_beat_tempo();
for( int32_t i = 0; i < _delay_num; i++ )
{
res = _delays[ i ]->Tone_Ready( beat_num, beat_tempo, _dst_sps );
if( res != pxtnOK ) return res;
}
for( int32_t i = 0; i < _ovdrv_num; i++ )
{
_ovdrvs[ i ]->Tone_Ready();
}
for( int32_t i = 0; i < _woice_num; i++ )
{
res = _woices[ i ]->Tone_Ready( _ptn_bldr, _dst_sps );
if( res != pxtnOK ) return res;
}
return pxtnOK;
}
bool pxtnService::tones_clear()
{
if( !_b_init ) return false;
for( int32_t i = 0; i < _delay_num; i++ ) _delays[ i ]->Tone_Clear();
for( int32_t i = 0; i < _unit_num; i++ ) _units [ i ]->Tone_Clear();
return true;
}
int32_t pxtnService::Delay_Num() const{ return _b_init ? _delay_num : 0; }
int32_t pxtnService::Delay_Max() const{ return _b_init ? _delay_max : 0; }
bool pxtnService::Delay_Set( int32_t idx, DELAYUNIT unit, float freq, float rate, int32_t group )
{
if( !_b_init ) return false;
if( idx >= _delay_num ) return false;
_delays[ idx ]->Set( unit, freq, rate, group );
return true;
}
bool pxtnService::Delay_Add( DELAYUNIT unit, float freq, float rate, int32_t group )
{
if( !_b_init ) return false;
if( _delay_num >= _delay_max ) return false;
_delays[ _delay_num ] = new pxtnDelay();
_delays[ _delay_num ]->Set( unit, freq, rate, group );
_delay_num++;
return true;
}
bool pxtnService::Delay_Remove( int32_t idx )
{
if( !_b_init ) return false;
if( idx >= _delay_num ) return false;
SAFE_DELETE( _delays[ idx ] );
_delay_num--;
for( int32_t i = idx; i < _delay_num; i++ ) _delays[ i ] = _delays[ i + 1 ];
_delays[ _delay_num ] = NULL;
return true;
}
pxtnDelay *pxtnService::Delay_Get( int32_t idx )
{
if( !_b_init ) return NULL;
if( idx < 0 || idx >= _delay_num ) return NULL;
return _delays[ idx ];
}
pxtnERR pxtnService::Delay_ReadyTone( int32_t idx )
{
if( !_b_init ) return pxtnERR_INIT;
if( idx < 0 || idx >= _delay_num ) return pxtnERR_param;
return _delays[ idx ]->Tone_Ready( master->get_beat_num(), master->get_beat_tempo(), _dst_sps );
}
int32_t pxtnService::OverDrive_Num() const{ return _b_init ? _ovdrv_num : 0; }
int32_t pxtnService::OverDrive_Max() const{ return _b_init ? _ovdrv_max : 0; }
bool pxtnService::OverDrive_Set( int32_t idx, float cut, float amp, int32_t group )
{
if( !_b_init ) return false;
if( idx >= _ovdrv_num ) return false;
_ovdrvs[ idx ]->Set( cut, amp, group );
return true;
}
bool pxtnService::OverDrive_Add( float cut, float amp, int32_t group )
{
if( !_b_init ) return false;
if( _ovdrv_num >= _ovdrv_max ) return false;
_ovdrvs[ _ovdrv_num ] = new pxtnOverDrive();
_ovdrvs[ _ovdrv_num ]->Set( cut, amp, group );
_ovdrv_num++;
return true;
}
bool pxtnService::OverDrive_Remove( int32_t idx )
{
if( !_b_init ) return false;
if( idx >= _ovdrv_num ) return false;
SAFE_DELETE( _ovdrvs[ idx ] );
_ovdrv_num--;
for( int32_t i = idx; i < _ovdrv_num; i++ ) _ovdrvs[ i ] = _ovdrvs[ i + 1 ];
_ovdrvs[ _ovdrv_num ] = NULL;
return true;
}
pxtnOverDrive *pxtnService::OverDrive_Get( int32_t idx )
{
if( !_b_init ) return NULL;
if( idx < 0 || idx >= _ovdrv_num ) return NULL;
return _ovdrvs[ idx ];
}
bool pxtnService::OverDrive_ReadyTone( int32_t idx )
{
if( !_b_init ) return false;
if( idx < 0 || idx >= _ovdrv_num ) return false;
_ovdrvs[ idx ]->Tone_Ready();
return true;
}
int32_t pxtnService::Woice_Num() const{ return _b_init ? _woice_num : 0; }
int32_t pxtnService::Woice_Max() const{ return _b_init ? _woice_max : 0; }
const pxtnWoice *pxtnService::Woice_Get( int32_t idx ) const
{
if( !_b_init ) return NULL;
if( idx < 0 || idx >= _woice_num ) return NULL;
return _woices[ idx ];
}
pxtnWoice *pxtnService::Woice_Get_variable( int32_t idx )
{
if( !_b_init ) return NULL;
if( idx < 0 || idx >= _woice_num ) return NULL;
return _woices[ idx ];
}
pxtnERR pxtnService::Woice_read( int32_t idx, pxtnDescriptor* desc, pxtnWOICETYPE type )
{
if( !_b_init ) return pxtnERR_INIT;
if( idx < 0 || idx >= _woice_max ) return pxtnERR_param;
if( idx > _woice_num ) return pxtnERR_param;
if( idx == _woice_num ){ _woices[ idx ] = new pxtnWoice(); _woice_num++; }
pxtnERR res = pxtnERR_VOID;
res = _woices[ idx ]->read( desc, type ); if( res != pxtnOK ){ Woice_Remove( idx ); return res; }
return res;
}
pxtnERR pxtnService::Woice_ReadyTone( int32_t idx )
{
if( !_b_init ) return pxtnERR_INIT;
if( idx < 0 || idx >= _woice_num ) return pxtnERR_param;
return _woices[ idx ]->Tone_Ready( _ptn_bldr, _dst_sps );
}
bool pxtnService::Woice_Remove( int32_t idx )
{
if( !_b_init ) return false;
if( idx < 0 || idx >= _woice_num ) return false;
SAFE_DELETE( _woices[ idx ] );
_woice_num--;
for( int32_t i = idx; i < _woice_num; i++ ) _woices[ i ] = _woices[ i + 1 ];
_woices[ _woice_num ] = NULL;
return true;
}
bool pxtnService::Woice_Replace( int32_t old_place, int32_t new_place )
{
if( !_b_init ) return false;
pxtnWoice* p_w = _woices[ old_place ];
int32_t max_place = _woice_num - 1;
if( new_place > max_place ) new_place = max_place;
if( new_place == old_place ) return true;
if( old_place < new_place )
{
for( int32_t w = old_place; w < new_place; w++ ){ if( _woices[ w ] ) _woices[ w ] = _woices[ w + 1 ]; }
}
else
{
for( int32_t w = old_place; w > new_place; w-- ){ if( _woices[ w ] ) _woices[ w ] = _woices[ w - 1 ]; }
}
_woices[ new_place ] = p_w;
return true;
}
int32_t pxtnService::Unit_Num() const{ return _b_init ? _unit_num : 0; }
int32_t pxtnService::Unit_Max() const{ return _b_init ? _unit_max : 0; }
const pxtnUnit *pxtnService::Unit_Get( int32_t idx ) const
{
if( !_b_init ) return NULL;
if( idx < 0 || idx >= _unit_num ) return NULL;
return _units[ idx ];
}
pxtnUnit *pxtnService::Unit_Get_variable( int32_t idx )
{
if( !_b_init ) return NULL;
if( idx < 0 || idx >= _unit_num ) return NULL;
return _units[ idx ];
}
bool pxtnService::Unit_AddNew()
{
if( _unit_num >= _unit_max ) return false;
_units[ _unit_num ] = new pxtnUnit();
_unit_num++;
return true;
}
bool pxtnService::Unit_Remove( int32_t idx )
{
if( !_b_init ) return false;
if( idx < 0 || idx >= _unit_num ) return false;
SAFE_DELETE( _units[ idx ] );
_unit_num--;
for( int32_t i = idx; i < _unit_num; i++ ) _units[ i ] = _units[ i + 1 ];
_units[ _unit_num ] = NULL;
return true;
}
bool pxtnService::Unit_Replace( int32_t old_place, int32_t new_place )
{
if( !_b_init ) return false;
pxtnUnit* p_w = _units[ old_place ];
int32_t max_place = _unit_num - 1;
if( new_place > max_place ) new_place = max_place;
if( new_place == old_place ) return true;
if( old_place < new_place )
{
for( int32_t w = old_place; w < new_place; w++ ){ if( _units[ w ] ) _units[ w ] = _units[ w + 1 ]; }
}
else
{
for( int32_t w = old_place; w > new_place; w-- ){ if( _units[ w ] ) _units[ w ] = _units[ w - 1 ]; }
}
_units[ new_place ] = p_w;
return true;
}
bool pxtnService::Unit_SetOpratedAll( bool b )
{
if( !_b_init ) return false;
for( int32_t u = 0; u < _unit_num; u++ )
{
_units[ u ]->set_operated( b );
if( b ) _units[ u ]->set_played( true );
}
return true;
}
bool pxtnService::Unit_Solo( int idx )
{
if( !_b_init ) return false;
for( int32_t u = 0; u < _unit_num; u++ )
{
if( u == idx ) _units[ u ]->set_played( true );
else _units[ u ]->set_played( false );
}
return false;
}
bool pxtnService::set_destination_quality( int32_t ch_num, int32_t sps )
{
if( !_b_init ) return false;
switch( ch_num )
{
case 1: break;
case 2: break;
default: return false;
}
_dst_ch_num = ch_num;
_dst_sps = sps ;
_dst_byte_per_smp = pxtnBITPERSAMPLE / 8 * ch_num;
return true;
}
bool pxtnService::get_destination_quality( int32_t *p_ch_num, int32_t *p_sps ) const
{
if( !_b_init ) return false;
if( p_ch_num ) *p_ch_num = _dst_ch_num;
if( p_sps ) *p_sps = _dst_sps ;
return true;
}
bool pxtnService::set_sampled_callback ( pxtnSampledCallback proc, void* user )
{
if( !_b_init ) return false;
_sampled_proc = proc;
_sampled_user = user;
return true;
}
static _enum_Tag _CheckTagCode( const char *p_code )
{
if( !memcmp( p_code, _code_antiOPER , _CODESIZE ) ) return _TAG_antiOPER;
else if( !memcmp( p_code, _code_x1x_PROJ , _CODESIZE ) ) return _TAG_x1x_PROJ;
else if( !memcmp( p_code, _code_x1x_UNIT , _CODESIZE ) ) return _TAG_x1x_UNIT;
else if( !memcmp( p_code, _code_x1x_PCM , _CODESIZE ) ) return _TAG_x1x_PCM;
else if( !memcmp( p_code, _code_x1x_EVEN , _CODESIZE ) ) return _TAG_x1x_EVEN;
else if( !memcmp( p_code, _code_x1x_END , _CODESIZE ) ) return _TAG_x1x_END;
else if( !memcmp( p_code, _code_x3x_pxtnUNIT, _CODESIZE ) ) return _TAG_x3x_pxtnUNIT;
else if( !memcmp( p_code, _code_x4x_evenMAST, _CODESIZE ) ) return _TAG_x4x_evenMAST;
else if( !memcmp( p_code, _code_x4x_evenUNIT, _CODESIZE ) ) return _TAG_x4x_evenUNIT;
else if( !memcmp( p_code, _code_num_UNIT , _CODESIZE ) ) return _TAG_num_UNIT;
else if( !memcmp( p_code, _code_Event_V5 , _CODESIZE ) ) return _TAG_Event_V5;
else if( !memcmp( p_code, _code_MasterV5 , _CODESIZE ) ) return _TAG_MasterV5;
else if( !memcmp( p_code, _code_matePCM , _CODESIZE ) ) return _TAG_matePCM ;
else if( !memcmp( p_code, _code_matePTV , _CODESIZE ) ) return _TAG_matePTV ;
else if( !memcmp( p_code, _code_matePTN , _CODESIZE ) ) return _TAG_matePTN ;
else if( !memcmp( p_code, _code_mateOGGV , _CODESIZE ) ) return _TAG_mateOGGV;
else if( !memcmp( p_code, _code_effeDELA , _CODESIZE ) ) return _TAG_effeDELA;
else if( !memcmp( p_code, _code_effeOVER , _CODESIZE ) ) return _TAG_effeOVER;
else if( !memcmp( p_code, _code_textNAME , _CODESIZE ) ) return _TAG_textNAME;
else if( !memcmp( p_code, _code_textCOMM , _CODESIZE ) ) return _TAG_textCOMM;
else if( !memcmp( p_code, _code_assiUNIT , _CODESIZE ) ) return _TAG_assiUNIT;
else if( !memcmp( p_code, _code_assiWOIC , _CODESIZE ) ) return _TAG_assiWOIC;
else if( !memcmp( p_code, _code_pxtoneND , _CODESIZE ) ) return _TAG_pxtoneND;
return _TAG_Unknown;
}
bool pxtnService::clear()
{
if( !_b_init ) return false;
if( !_b_edit ) _moo_b_valid_data = false;
if( !text->set_name_buf ( "", 0 ) ) return false;
if( !text->set_comment_buf( "", 0 ) ) return false;
evels->Clear();
for( int32_t i = 0; i < _delay_num; i++ ) SAFE_DELETE( _delays[ i ] ); _delay_num = 0;
for( int32_t i = 0; i < _delay_num; i++ ) SAFE_DELETE( _ovdrvs[ i ] ); _ovdrv_num = 0;
for( int32_t i = 0; i < _woice_num; i++ ) SAFE_DELETE( _woices[ i ] ); _woice_num = 0;
for( int32_t i = 0; i < _unit_num ; i++ ) SAFE_DELETE( _units [ i ] ); _unit_num = 0;
master->Reset();
if( !_b_edit ) evels->Release();
else evels->Clear ();
return true;
}
pxtnERR pxtnService::_io_Read_Delay( pxtnDescriptor *p_doc )
{
if( !_b_init ) return pxtnERR_INIT;
if( !_delays ) return pxtnERR_INIT;
if( _delay_num >= _delay_max ) return pxtnERR_fmt_unknown;
pxtnERR res = pxtnERR_VOID;
pxtnDelay* delay = new pxtnDelay();
res = delay->Read( p_doc ); if( res != pxtnOK ) goto term;
res = pxtnOK;
term:
if( res == pxtnOK ){ _delays[ _delay_num ] = delay; _delay_num++; }
else { SAFE_DELETE( delay ); }
return res;
}
pxtnERR pxtnService::_io_Read_OverDrive( pxtnDescriptor *p_doc )
{
if( !_b_init ) return pxtnERR_INIT;
if( !_ovdrvs ) return pxtnERR_INIT;
if( _ovdrv_num >= _ovdrv_max ) return pxtnERR_fmt_unknown;
pxtnERR res = pxtnERR_VOID;
pxtnOverDrive *ovdrv = new pxtnOverDrive();
res = ovdrv->Read( p_doc ); if( res != pxtnOK ) goto term;
res = pxtnOK;
term:
if( res == pxtnOK ){ _ovdrvs[ _ovdrv_num ] = ovdrv; _ovdrv_num++; }
else { SAFE_DELETE( ovdrv ); }
return res;
}
pxtnERR pxtnService::_io_Read_Woice( pxtnDescriptor *p_doc, pxtnWOICETYPE type )
{
pxtnERR res = pxtnERR_VOID;
if( !_b_init ) return pxtnERR_INIT;
if( !_woices ) return pxtnERR_INIT;
if( _woice_num >= _woice_max ) return pxtnERR_woice_full;
pxtnWoice *woice = new pxtnWoice();
switch( type )
{
case pxtnWOICE_PCM : res = woice->io_matePCM_r( p_doc ); if( res != pxtnOK ) goto term; break;
case pxtnWOICE_PTV : res = woice->io_matePTV_r( p_doc ); if( res != pxtnOK ) goto term; break;
case pxtnWOICE_PTN : res = woice->io_matePTN_r( p_doc ); if( res != pxtnOK ) goto term; break;
case pxtnWOICE_OGGV:
#ifdef pxINCLUDE_OGGVORBIS
res = woice->io_mateOGGV_r( p_doc );
if( res != pxtnOK ) goto term;
#else
res = pxtnERR_ogg_no_supported; goto term;
#endif
break;
default: res = pxtnERR_fmt_unknown; goto term;
}
_woices[ _woice_num ] = woice; _woice_num++;
res = pxtnOK;
term:
if( res != pxtnOK ) SAFE_DELETE( woice );
return res;
}
pxtnERR pxtnService::_io_Read_OldUnit( pxtnDescriptor *p_doc, int32_t ver )
{
if( !_b_init ) return pxtnERR_INIT;
if( !_units ) return pxtnERR_INIT;
if( _unit_num >= _unit_max ) return pxtnERR_fmt_unknown;
pxtnERR res = pxtnERR_VOID ;
pxtnUnit* unit = new pxtnUnit();
int32_t group = 0;
switch( ver )
{
case 1: if( !unit->Read_v1x ( p_doc, &group ) ) goto term; break;
case 3: res = unit->Read_v3x( p_doc, &group ); if( res != pxtnOK ) goto term; break;
default: res = pxtnERR_fmt_unknown; goto term;
}
if( group >= _group_num ) group = _group_num - 1;
evels->x4x_Read_Add( 0, (uint8_t)_unit_num, EVENTKIND_GROUPNO, (int32_t)group );
evels->x4x_Read_NewKind();
evels->x4x_Read_Add( 0, (uint8_t)_unit_num, EVENTKIND_VOICENO, (int32_t)_unit_num );
evels->x4x_Read_NewKind();
res = pxtnOK;
term:
if( res == pxtnOK ){ _units[ _unit_num ] = unit; _unit_num++; }
else { SAFE_DELETE( unit ); }
return res;
}
typedef struct
{
uint16_t woice_index;
uint16_t rrr;
char name[ pxtnMAX_TUNEWOICENAME ];
}
_ASSIST_WOICE;
bool pxtnService::_io_assiWOIC_w( pxtnDescriptor *p_doc, int32_t idx ) const
{
if( !_b_init ) return false;
_ASSIST_WOICE assi = {0};
int32_t size;
int32_t name_size = 0;
const char* p_name = _woices[ idx ]->get_name_buf( &name_size );
if( name_size > pxtnMAX_TUNEWOICENAME ) return false;
memcpy( assi.name, p_name, name_size );
assi.woice_index = (uint16_t)idx;
size = sizeof( _ASSIST_WOICE );
if( !p_doc->w_asfile( &size, sizeof(uint32_t), 1 ) ) return false;
if( !p_doc->w_asfile( &assi, size, 1 ) ) return false;
return true;
}
pxtnERR pxtnService::_io_assiWOIC_r( pxtnDescriptor *p_doc )
{
if( !_b_init ) return pxtnERR_INIT;
_ASSIST_WOICE assi = {0};
int32_t size = 0 ;
if( !p_doc->r( &size, 4, 1 ) ) return pxtnERR_desc_r ;
if( size != sizeof(assi) ) return pxtnERR_fmt_unknown;
if( !p_doc->r( &assi, size, 1 ) ) return pxtnERR_desc_r ;
if( assi.rrr ) return pxtnERR_fmt_unknown;
if( assi.woice_index >= _woice_num ) return pxtnERR_fmt_unknown;
if( !_woices[ assi.woice_index ]->set_name_buf( assi.name, pxtnMAX_TUNEWOICENAME ) ) return pxtnERR_FATAL;
return pxtnOK;
}
typedef struct
{
uint16_t unit_index;
uint16_t rrr;
char name[ pxtnMAX_TUNEUNITNAME ];
}
_ASSIST_UNIT;
bool pxtnService::_io_assiUNIT_w( pxtnDescriptor *p_doc, int32_t idx ) const
{
if( !_b_init ) return false;
_ASSIST_UNIT assi = {0};
int32_t size;
int32_t name_size;
const char* p_name = _units[ idx ]->get_name_buf( &name_size );
memcpy( assi.name, p_name, name_size );
assi.unit_index = (uint16_t)idx;
size = sizeof(assi);
if( !p_doc->w_asfile( &size, sizeof(uint32_t), 1 ) ) return false;
if( !p_doc->w_asfile( &assi, size , 1 ) ) return false;
return true;
}
pxtnERR pxtnService::_io_assiUNIT_r( pxtnDescriptor *p_doc )
{
if( !_b_init ) return pxtnERR_INIT;
_ASSIST_UNIT assi = {0};
int32_t size;
if( !p_doc->r( &size, 4, 1 ) ) return pxtnERR_desc_r ;
if( size != sizeof(assi) ) return pxtnERR_fmt_unknown;
if( !p_doc->r( &assi, sizeof(assi), 1 ) ) return pxtnERR_desc_r ;
if( assi.rrr ) return pxtnERR_fmt_unknown;
if( assi.unit_index >= _unit_num ) return pxtnERR_fmt_unknown;
if( !_units[ assi.unit_index ]->set_name_buf( assi.name, pxtnMAX_TUNEUNITNAME ) ) return pxtnERR_FATAL;
return pxtnOK;
}
typedef struct
{
int16_t num;
int16_t rrr;
}
_NUM_UNIT;
bool pxtnService::_io_UNIT_num_w( pxtnDescriptor *p_doc ) const
{
if( !_b_init ) return false;
_NUM_UNIT data;
int32_t size;
memset( &data, 0, sizeof( _NUM_UNIT ) );
data.num = (int16_t)_unit_num;
size = sizeof(_NUM_UNIT);
if( !p_doc->w_asfile( &size, sizeof(int32_t), 1 ) ) return false;
if( !p_doc->w_asfile( &data, size , 1 ) ) return false;
return true;
}
pxtnERR pxtnService::_io_UNIT_num_r ( pxtnDescriptor *p_doc, int32_t* p_num )
{
if( !_b_init ) return pxtnERR_INIT;
_NUM_UNIT data = {0};
int32_t size = 0 ;
if( !p_doc->r( &size, 4, 1 ) ) return pxtnERR_desc_r ;
if( size != sizeof( _NUM_UNIT ) ) return pxtnERR_fmt_unknown;
if( !p_doc->r( &data, sizeof( _NUM_UNIT ), 1 ) ) return pxtnERR_desc_r ;
if( data.rrr ) return pxtnERR_fmt_unknown;
if( data.num > _unit_max ) return pxtnERR_fmt_new ;
if( data.num < 0 ) return pxtnERR_fmt_unknown;
*p_num = data.num;
return pxtnOK;
}
pxtnERR pxtnService::write( pxtnDescriptor *p_doc, bool b_tune, uint16_t exe_ver )
{
if( !_b_init ) return pxtnERR_INIT;
bool b_ret = false;
int32_t rough = b_tune ? 10 : 1;
uint16_t rrr = 0;
pxtnERR res = pxtnERR_VOID;
if( b_tune ){ if( !p_doc->w_asfile( _code_tune_v5, 1, _VERSIONSIZE ) ){ res = pxtnERR_desc_w; goto End; } }
else { if( !p_doc->w_asfile( _code_proj_v5, 1, _VERSIONSIZE ) ){ res = pxtnERR_desc_w; goto End; } }
if( !p_doc->w_asfile( &exe_ver, sizeof(uint16_t), 1 ) ){ res = pxtnERR_desc_w; goto End; }
if( !p_doc->w_asfile( &rrr , sizeof(uint16_t), 1 ) ){ res = pxtnERR_desc_w; goto End; }
if( !p_doc->w_asfile( _code_MasterV5 , 1, _CODESIZE ) ){ res = pxtnERR_desc_w; goto End; }
if( !master->io_w_v5( p_doc, rough ) ){ res = pxtnERR_desc_w; goto End; }
if( !p_doc->w_asfile( _code_Event_V5, 1, _CODESIZE ) ){ res = pxtnERR_desc_w; goto End; }
if( !evels->io_Write( p_doc, rough ) ){ res = pxtnERR_desc_w; goto End; }
if( text->is_name_buf() )
{
if( !p_doc->w_asfile( _code_textNAME, 1, _CODESIZE ) ){ res = pxtnERR_desc_w; goto End; }
if( !text->Name_w( p_doc ) ){ res = pxtnERR_desc_w; goto End; }
}
if( text->is_comment_buf() )
{
if( !p_doc->w_asfile( _code_textCOMM, 1, _CODESIZE ) ){ res = pxtnERR_desc_w; goto End; }
if( !text->Comment_w( p_doc ) ){ res = pxtnERR_desc_w; goto End; }
}
for( int32_t d = 0; d < _delay_num; d++ )
{
if( !p_doc->w_asfile( _code_effeDELA, 1, _CODESIZE ) ){ res = pxtnERR_desc_w; goto End; }
if( !_delays[ d ]->Write( p_doc ) ){ res = pxtnERR_desc_w; goto End; }
}
for( int32_t o = 0; o < _ovdrv_num; o++ )
{
if( !p_doc->w_asfile( _code_effeOVER, 1, _CODESIZE ) ){ res = pxtnERR_desc_w; goto End; }
if( !_ovdrvs[ o ]->Write( p_doc ) ){ res = pxtnERR_desc_w; goto End; }
}
for( int32_t w = 0; w < _woice_num; w++ )
{
pxtnWoice * p_w = _woices[ w ];
switch( p_w->get_type() )
{
case pxtnWOICE_PCM:
if( !p_doc->w_asfile( _code_matePCM , 1, _CODESIZE ) ){ res = pxtnERR_desc_w; goto End; }
if( !p_w->io_matePCM_w ( p_doc ) ){ res = pxtnERR_desc_w; goto End; }
break;
case pxtnWOICE_PTV:
if( !p_doc->w_asfile( _code_matePTV , 1, _CODESIZE ) ){ res = pxtnERR_desc_w; goto End; }
if( !p_w->io_matePTV_w ( p_doc ) ){ res = pxtnERR_desc_w; goto End; }
break;
case pxtnWOICE_PTN:
if( !p_doc->w_asfile( _code_matePTN , 1, _CODESIZE ) ){ res = pxtnERR_desc_w; goto End; }
if( !p_w->io_matePTN_w ( p_doc ) ){ res = pxtnERR_desc_w; goto End; }
break;
case pxtnWOICE_OGGV:
#ifdef pxINCLUDE_OGGVORBIS
if( !p_doc->w_asfile( _code_mateOGGV, 1, _CODESIZE ) ){ res = pxtnERR_desc_w; goto End; }
if( !p_w->io_mateOGGV_w( p_doc ) ){ res = pxtnERR_desc_w; goto End; }
#else
res = pxtnERR_ogg_no_supported; goto End;
#endif
break;
default:
res = pxtnERR_inv_data; goto End;
}
if( !b_tune && p_w->is_name_buf() )
{
if( !p_doc->w_asfile( _code_assiWOIC, 1, _CODESIZE ) ){ res = pxtnERR_desc_w; goto End; }
if( !_io_assiWOIC_w( p_doc, w ) ){ res = pxtnERR_desc_w; goto End; }
}
}
if( !p_doc->w_asfile( _code_num_UNIT, 1, _CODESIZE ) ){ res = pxtnERR_desc_w; goto End; }
if( !_io_UNIT_num_w( p_doc ) ){ res = pxtnERR_desc_w; goto End; }
for( int32_t u = 0; u < _unit_num; u++ )
{
if( !b_tune && _units[ u ]->is_name_buf() )
{
if( !p_doc->w_asfile( _code_assiUNIT, 1, _CODESIZE) ){ res = pxtnERR_desc_w; goto End; }
if( !_io_assiUNIT_w( p_doc, u ) ){ res = pxtnERR_desc_w; goto End; }
}
}
{
int32_t end_size = 0;
if( !p_doc->w_asfile( _code_pxtoneND, 1, _CODESIZE ) ){ res = pxtnERR_desc_w; goto End; }
if( !p_doc->w_asfile( &end_size , 4, 1 ) ){ res = pxtnERR_desc_w; goto End; }
}
res = pxtnOK;
End:
return res;
}
pxtnERR pxtnService::_ReadTuneItems( pxtnDescriptor *p_doc )
{
if( !_b_init ) return pxtnERR_INIT;
pxtnERR res = pxtnERR_VOID;
bool b_end = false;
char code[ _CODESIZE + 1 ] = {'\0'};
while( !b_end )
{
if( !p_doc->r( code, 1, _CODESIZE ) ){ res = pxtnERR_desc_r; goto term; }
_enum_Tag tag = _CheckTagCode( code );
switch( tag )
{
case _TAG_antiOPER : res = pxtnERR_anti_opreation; goto term;
case _TAG_num_UNIT :
{
int32_t num = 0;
res = _io_UNIT_num_r( p_doc, &num ); if( res != pxtnOK ) goto term;
for( int32_t i = 0; i < num; i++ ) _units[ i ] = new pxtnUnit();
_unit_num = num;
break;
}
case _TAG_MasterV5: res = master->io_r_v5( p_doc ); if( res != pxtnOK ) goto term; break;
case _TAG_Event_V5: res = evels->io_Read ( p_doc ); if( res != pxtnOK ) goto term; break;
case _TAG_matePCM : res = _io_Read_Woice( p_doc, pxtnWOICE_PCM ); if( res != pxtnOK ) goto term; break;
case _TAG_matePTV : res = _io_Read_Woice( p_doc, pxtnWOICE_PTV ); if( res != pxtnOK ) goto term; break;
case _TAG_matePTN : res = _io_Read_Woice( p_doc, pxtnWOICE_PTN ); if( res != pxtnOK ) goto term; break;
case _TAG_mateOGGV:
#ifdef pxINCLUDE_OGGVORBIS
res = _io_Read_Woice( p_doc, pxtnWOICE_OGGV );
if( res != pxtnOK ) goto term;
#else
res = pxtnERR_ogg_no_supported; goto term;
#endif
break;
case _TAG_effeDELA : res = _io_Read_Delay ( p_doc ); if( res != pxtnOK ) goto term; break;
case _TAG_effeOVER : res = _io_Read_OverDrive ( p_doc ); if( res != pxtnOK ) goto term; break;
case _TAG_textNAME : if( !text->Name_r ( p_doc ) ){ res = pxtnERR_desc_r; goto term; } break;
case _TAG_textCOMM : if( !text->Comment_r ( p_doc ) ){ res = pxtnERR_desc_r; goto term; } break;
case _TAG_assiWOIC : res = _io_assiWOIC_r ( p_doc ); if( res != pxtnOK ) goto term; break;
case _TAG_assiUNIT : res = _io_assiUNIT_r ( p_doc ); if( res != pxtnOK ) goto term; break;
case _TAG_pxtoneND : b_end = true; break;
case _TAG_x4x_evenMAST: res = master->io_r_x4x ( p_doc ); if( res != pxtnOK ) goto term; break;
case _TAG_x4x_evenUNIT: res = evels ->io_Unit_Read_x4x_EVENT( p_doc, false, true ); if( res != pxtnOK ) goto term; break;
case _TAG_x3x_pxtnUNIT: res = _io_Read_OldUnit ( p_doc, 3 ); if( res != pxtnOK ) goto term; break;
case _TAG_x1x_PROJ : if( !_x1x_Project_Read ( p_doc ) ){ res = pxtnERR_desc_r; goto term; } break;
case _TAG_x1x_UNIT : res = _io_Read_OldUnit ( p_doc, 1 ); if( res != pxtnOK ) goto term; break;
case _TAG_x1x_PCM : res = _io_Read_Woice ( p_doc, pxtnWOICE_PCM ); if( res != pxtnOK ) goto term; break;
case _TAG_x1x_EVEN : res = evels ->io_Unit_Read_x4x_EVENT( p_doc, true, false ); if( res != pxtnOK ) goto term; break;
case _TAG_x1x_END : b_end = true; break;
default: res = pxtnERR_fmt_unknown; goto term;
}
}
res = pxtnOK;
term:
return res;
}
#define _MAX_FMTVER_x1x_EVENTNUM 10000
pxtnERR pxtnService::_ReadVersion( pxtnDescriptor *p_doc, _enum_FMTVER *p_fmt_ver, uint16_t *p_exe_ver )
{
if( !_b_init ) return pxtnERR_INIT;
char version[ _VERSIONSIZE ] = {'\0'};
uint16_t dummy;
if( !p_doc->r( version, 1, _VERSIONSIZE ) )return pxtnERR_desc_r;
if( !memcmp( version, _code_proj_x1x , _VERSIONSIZE ) ){ *p_fmt_ver = _enum_FMTVER_x1x; *p_exe_ver = 0; return pxtnOK; }
else if( !memcmp( version, _code_proj_x2x , _VERSIONSIZE ) ){ *p_fmt_ver = _enum_FMTVER_x2x; *p_exe_ver = 0; return pxtnOK; }
else if( !memcmp( version, _code_proj_x3x , _VERSIONSIZE ) ){ *p_fmt_ver = _enum_FMTVER_x3x; }
else if( !memcmp( version, _code_proj_x4x , _VERSIONSIZE ) ){ *p_fmt_ver = _enum_FMTVER_x4x; }
else if( !memcmp( version, _code_proj_v5 , _VERSIONSIZE ) ){ *p_fmt_ver = _enum_FMTVER_v5 ; }
else if( !memcmp( version, _code_tune_x2x , _VERSIONSIZE ) ){ *p_fmt_ver = _enum_FMTVER_x2x; *p_exe_ver = 0; return pxtnOK; }
else if( !memcmp( version, _code_tune_x3x , _VERSIONSIZE ) ){ *p_fmt_ver = _enum_FMTVER_x3x; }
else if( !memcmp( version, _code_tune_x4x , _VERSIONSIZE ) ){ *p_fmt_ver = _enum_FMTVER_x4x; }
else if( !memcmp( version, _code_tune_v5 , _VERSIONSIZE ) ){ *p_fmt_ver = _enum_FMTVER_v5 ; }
else return pxtnERR_fmt_unknown;
if( !p_doc->r( p_exe_ver, sizeof(uint16_t), 1 ) ) return pxtnERR_desc_r;
if( !p_doc->r( &dummy , sizeof(uint16_t), 1 ) ) return pxtnERR_desc_r;
return pxtnOK;
}
bool pxtnService::_x3x_TuningKeyEvent()
{
if( !_b_init ) return false;
if( _unit_num > _woice_num ) return false;
for( int32_t u = 0; u < _unit_num; u++ )
{
if( u >= _woice_num ) return false;
int32_t change_value = _woices[ u ]->get_x3x_basic_key() - EVENTDEFAULT_BASICKEY;
if( !evels->get_Count( (uint8_t)u, (uint8_t)EVENTKIND_KEY ) )
{
evels->Record_Add_i( 0, (uint8_t)u, EVENTKIND_KEY, (int32_t)0x6000 );
}
evels->Record_Value_Change( 0, -1, (uint8_t)u, EVENTKIND_KEY, change_value );
}
return true;
}
bool pxtnService::_x3x_AddTuningEvent()
{
if( !_b_init ) return false;
if( _unit_num > _woice_num ) return false;
for( int32_t u = 0; u < _unit_num; u++ )
{
float tuning = _woices[ u ]->get_x3x_tuning();
if( tuning ) evels->Record_Add_f( 0, (uint8_t)u, EVENTKIND_TUNING, tuning );
}
return true;
}
bool pxtnService::_x3x_SetVoiceNames()
{
if( !_b_init ) return false;
for( int32_t i = 0; i < _woice_num; i++ )
{
char name[ pxtnMAX_TUNEWOICENAME + 1 ];
sprintf( name, "voice_%02d", i );
_woices[ i ]->set_name_buf( name, 8 );
}
return true;
}
pxtnERR pxtnService::_pre_count_event( pxtnDescriptor *p_doc, int32_t* p_count )
{
if( !_b_init ) return pxtnERR_INIT ;
if( !p_count ) return pxtnERR_param;
pxtnERR res = pxtnERR_VOID;
bool b_end = false;
int32_t count = 0;
int32_t c = 0;
int32_t size = 0;
char code[ _CODESIZE + 1 ] = {'\0'};
uint16_t exe_ver = 0;
_enum_FMTVER fmt_ver = _enum_FMTVER_unknown;
res = _ReadVersion( p_doc, &fmt_ver, &exe_ver ); if( res != pxtnOK ) goto term;
if( fmt_ver == _enum_FMTVER_x1x )
{
count = _MAX_FMTVER_x1x_EVENTNUM;
res = pxtnOK;
goto term;
}
while( !b_end )
{
if( !p_doc->r( code, 1, _CODESIZE ) ){ res = pxtnERR_desc_r; goto term; }
switch( _CheckTagCode( code ) )
{
case _TAG_Event_V5 : count += evels ->io_Read_EventNum ( p_doc ); break;
case _TAG_MasterV5 : count += master->io_r_v5_EventNum ( p_doc ); break;
case _TAG_x4x_evenMAST: count += master->io_r_x4x_EventNum( p_doc ); break;
case _TAG_x4x_evenUNIT: res = evels ->io_Read_x4x_EventNum( p_doc, &c ); if( res != pxtnOK ) goto term; count += c; break;
case _TAG_pxtoneND : b_end = true; break;
case _TAG_antiOPER :
case _TAG_num_UNIT :
case _TAG_x3x_pxtnUNIT:
case _TAG_matePCM :
case _TAG_matePTV :
case _TAG_matePTN :
case _TAG_mateOGGV :
case _TAG_effeDELA :
case _TAG_effeOVER :
case _TAG_textNAME :
case _TAG_textCOMM :
case _TAG_assiUNIT :
case _TAG_assiWOIC :
if( !p_doc->r( &size, sizeof(int32_t), 1 ) ){ res = pxtnERR_desc_r; goto term; }
if( !p_doc->seek( pxtnSEEK_cur, size ) ){ res = pxtnERR_desc_r; goto term; }
break;
case _TAG_x1x_PROJ :
case _TAG_x1x_UNIT :
case _TAG_x1x_PCM :
case _TAG_x1x_EVEN :
case _TAG_x1x_END : res = pxtnERR_x1x_ignore; goto term;
default : res = pxtnERR_FATAL ; goto term;
}
}
if( fmt_ver <= _enum_FMTVER_x3x ) count += pxtnMAX_TUNEUNITSTRUCT * 4;
res = pxtnOK;
term:
if( res != pxtnOK ) *p_count = 0;
else *p_count = count;
return res;
}
pxtnERR pxtnService::read( pxtnDescriptor *p_doc )
{
if( !_b_init ) return pxtnERR_INIT;
pxtnERR res = pxtnERR_VOID;
uint16_t exe_ver = 0;
_enum_FMTVER fmt_ver = _enum_FMTVER_unknown;
int32_t event_num = 0;
clear();
res = _pre_count_event( p_doc, &event_num );
if( res != pxtnOK ) goto term;
p_doc->seek( pxtnSEEK_set, 0 );
if( _b_fix_evels_num )
{
if( event_num > evels->get_Num_Max() ){ res = pxtnERR_too_much_event; goto term; }
}
else
{
if( !evels->Allocate( event_num ) ){ res = pxtnERR_memory ; goto term; }
}
res = _ReadVersion( p_doc, &fmt_ver, &exe_ver ); if( res != pxtnOK ) goto term;
if( fmt_ver >= _enum_FMTVER_v5 ) evels->Linear_Start ();
else evels->x4x_Read_Start();
res = _ReadTuneItems( p_doc ); if( res != pxtnOK ) goto term;
if( fmt_ver >= _enum_FMTVER_v5 ) evels->Linear_End( true );
if( fmt_ver <= _enum_FMTVER_x3x )
{
if( !_x3x_TuningKeyEvent() ){ res = pxtnERR_x3x_key ; goto term; }
if( !_x3x_AddTuningEvent() ){ res = pxtnERR_x3x_add_tuning; goto term; }
_x3x_SetVoiceNames();
}
if( _b_edit && master->get_beat_clock() != EVENTDEFAULT_BEATCLOCK ){ res = pxtnERR_deny_beatclock; goto term; }
{
int32_t clock1 = evels ->get_Max_Clock ();
int32_t clock2 = master->get_last_clock();
if( clock1 > clock2 ) master->AdjustMeasNum( clock1 );
else master->AdjustMeasNum( clock2 );
}
_moo_b_valid_data = true;
res = pxtnOK;
term:
if( res != pxtnOK ) clear();
return res;
}
#define _MAX_PROJECTNAME_x1x 16
typedef struct
{
char x1x_name[_MAX_PROJECTNAME_x1x];
float x1x_beat_tempo;
uint16_t x1x_beat_clock;
uint16_t x1x_beat_num;
uint16_t x1x_beat_note;
uint16_t x1x_meas_num;
uint16_t x1x_channel_num;
uint16_t x1x_bps;
uint32_t x1x_sps;
}
_x1x_PROJECT;
bool pxtnService::_x1x_Project_Read( pxtnDescriptor *p_doc )
{
if( !_b_init ) return false;
_x1x_PROJECT prjc = {0};
int32_t beat_num, beat_clock;
int32_t size;
float beat_tempo;
if( !p_doc->r( &size, 4, 1 ) ) return false;
if( !p_doc->r( &prjc, sizeof( _x1x_PROJECT ), 1 ) ) return false;
beat_num = prjc.x1x_beat_num ;
beat_tempo = prjc.x1x_beat_tempo;
beat_clock = prjc.x1x_beat_clock;
int32_t ns = 0;
for( ns; ns < _MAX_PROJECTNAME_x1x; ns++ ){ if( !prjc.x1x_name[ ns ] ) break; }
text->set_name_buf( prjc.x1x_name, ns );
master->Set( beat_num, beat_tempo, beat_clock );
return true;
}