⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bitaudio.cpp

📁 2002年
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include <string.h>
#include "bitaudio.h"
#include "worldmodel.h"
#include "skill.h"
#include "log.h"
#include "agent.h"
#include "netif.h"

#define Bitsperbyte 6
//#define _LONG_AUDIO

#define CAudio_half_length 64.0f

#ifdef _LONG_AUDIO
#define CAudio_accuracy_bits 5
#else
#define CAudio_accuracy_bits 2
#endif 

#define CAudio_vel_length_bits 5
#define CAudio_vel_angle_bits 6
#define CAudio_vel_length_grain 0.1f
#define CAudio_vel_angle_grain 6.0f

const int CAudio_max_accuracy = (int)pow(2, CAudio_accuracy_bits);
/*************** CParse Bit************************/

CParseBit::CParseBit(){
	Clear();
}

/*Clear Buffer*/
void CParseBit::Clear(){
	buf_bits_len = 0;
	cur_buf_pos = 0;
	memset( buffer, 0, Max_Audio_Bytes );
}

/*Copy length bytes data from s to buffer*/
bool CParseBit::Load(unsigned char * s,int length){
	Clear();

	if (length > ServerParam::say_msg_size * Bitsperbyte) return false;
	memcpy(buffer, s, sizeof(char)*length);

	buf_bits_len = length * 8;
	cur_buf_pos = 0;
	return true;
}

/*	Copy n-bits data from s to the current pos of the buffer
	the buffer's current pos is moved accordingly.
*/
bool CParseBit::Add(unsigned char * s,int n){
	if (buf_bits_len+n > ServerParam::say_msg_size * Bitsperbyte) return false;

	int d0 = buf_bits_len % 8;	//缓冲区末指针指向所在字节的位数
	int l0 = buf_bits_len / 8;  //缓冲区末指针所在的字节
	int l1 = (n+7)/8;			//新添内容的字节数
	int l2 = n%8;
	//将最后一个字节的多余位清0.
	if(l2 >0){
		unsigned char mask = 255;
		mask = mask >> (8-l2);
		s[l1-1] &= mask;
	}
	unsigned char tmp;
	int i;
	for(i = 0; i<l1; i++){
		//以字节为单位添加数据
		tmp = s[i]; 
		tmp <<= d0;				
		buffer[l0+i] |=   tmp;

		tmp = s[i]; 
		tmp >>= (8-d0);	
		buffer[l0+i+1] |= tmp;
	}
	buf_bits_len +=  n;
	return true;
}

/*	Retrieve n-bits data starting from the current pos of the buffer to s
	the buffer's current pos is moved accordingly.
*/
bool CParseBit::Get(unsigned char * s,int n){
	if (cur_buf_pos+n > buf_bits_len) return false;

	int d0 = cur_buf_pos % 8;	//当前指针指向所在字节的位数
	int l0 = cur_buf_pos / 8;	//当前指针所在的字节数

	int d1 = n % 8;
	int	l1 = (n+7)/8;

	memset(s, 0, l1);

	unsigned char c;
	int i;
	for(i = 0; i < l1; i++){
		c = buffer[l0+i];
		c >>= d0;
		s[i] = c;

		c = buffer[l0+i+1];
		c <<= (8-d0);
		s[i] |=   c;
	}
	i --;
	if(d1 > 0){
		s[i] <<= 8-d1;
		s[i] >>= 8-d1;
	}

	cur_buf_pos += n;
	return true;
}

/*	Transient function 
	To reprensent data in the predefined format and stored in msg.
	1>transfated each byte into an integer
	2>print the integer followed with a separate_char into the end of msg.
*/
void CParseBit::TransferToChar(char* msg){
	Rewind();
	int bytes = buf_bits_len / Bitsperbyte;
	
	int remain = buf_bits_len % Bitsperbyte;
	unsigned char c;
	int i;
	for(i=0; i<bytes; i++){
		Get(&c, Bitsperbyte);
		msg[i] = AudioDatamap::map_into_printablechar((int)c);
	}
	if(remain > 0){
		Get(&c, remain);
		msg[i++] = AudioDatamap::map_into_printablechar((int)c);
	}
	if(i > 0){
		msg[i] = 0;
	}
}	
/*	Transient function 
	To parse the integer data in the string and concatnated them into byte buffer.
	1>read out each integer(ranged from 0-255)
	2>put it into the buffer as a byte data.
*/
void CParseBit::LoadFromChar(char* msg){
	Clear();

	unsigned char c;
	int i = 0;
	while(msg[i] != '"'){
		c = (unsigned char)AudioDatamap::map_from_printablechar(msg[i]); 
		Add(&c, Bitsperbyte);
		i ++;
	}
}

CBitAuditory::CBitAuditory(){
	range_exp = 5;	//32
	rec_range_exp = 5;	//32
}

void CBitAuditory::ParseMsg_Ball(CParseBit& pb){
	TimedData<NoiseVector> data;
	unsigned char acu, c_x, c_y, c_velx, c_vely, c_delay, c_ctrller;
	float x, y, delta;

	pb.Get(&acu, CAudio_accuracy_bits);// 2 bits specify the vector accuracy
	pb.Get(&c_x, bit_len(acu, rec_range_exp));/// x,y of vector
	pb.Get(&c_y, bit_len(acu, rec_range_exp));
	
	pb.Get(&c_delay, CAudio_accuracy_bits);
	pb.Get(&c_vely, CAudio_vel_angle_bits);
	pb.Get(&c_velx, CAudio_vel_length_bits);
	pb.Get(&c_ctrller,  CAudio_Num_bits);

#ifndef _LONG_AUDIO
	if(!IsFullRange(rec_range_exp) && 
		(!ball.IsValidObject() || ball.pos_delta > Max_ref_delta(rec_range_exp))){
		//can't utilize heard info for insufficient reference accuracy.
		return;
	}
	if(ball.Isforgot() && situation.playmode != PM_Play_On){
		DoLog("give up hear info");
		return;
	}
#endif
//parse pos data
	x = c2f_x(c_x, acu, rec_range_exp, ball.pos.x);
	y = c2f_y(c_y, acu, rec_range_exp, ball.pos.y);
	delta = accuracy_2_delta(acu);
	delta += Quantize_delta(acu);
	data.Setdata(NoiseVector(x, y, delta), parse_time);
	HearBallPos(data);
//parse vel data
	data.data.delta = c_delay;
	data.data.mean = Polar2Vector(c_velx * CAudio_vel_length_grain, 
				c_vely * CAudio_vel_angle_grain);
	HearBallVel(data);
	HearBallController((int)c_ctrller);
}

void CBitAuditory::ParseMsg_Ctrl(CParseBit& pb, int speaker){
	HearPass(parse_time);
	HearBallController(speaker);
	
	TimedData<NoiseVector> data;
	unsigned char acu, c_x, c_y;
	float x, y, delta;

	acu = 0;
	pb.Get(&c_x, bit_len(acu, rec_range_exp));/// x,y of vector
	pb.Get(&c_y, bit_len(acu, rec_range_exp));	

	Player* p = &GetPlayer(speaker);

#ifndef _LONG_AUDIO
	if(!IsFullRange(rec_range_exp) && 
		(!p->IsValidObject() || p->pos_delta > Max_ref_delta(rec_range_exp))){
		//can't utilize heard info for insufficient reference accuracy.
		return;
	}
#endif
//ball pos is close to player pos
	x = c2f_x(c_x, acu, rec_range_exp, p->pos.x);
	y = c2f_y(c_y, acu, rec_range_exp, p->pos.y);
	delta = accuracy_2_delta(acu);
	delta += Quantize_delta(acu);
	data.Setdata(NoiseVector(x, y, delta), parse_time);
	HearPlayerPos(data, speaker);

	data.data.delta += p->kickable_area;
	HearBallPos(data);

	data.data.delta = 0;
	data.data.mean = 0;
	HearBallVel(data);
}

void CBitAuditory::ParseMsg_Pass(CParseBit& pb){
	HearPass(parse_time);
//the following is ball msg with acu always be 0.
	TimedData<NoiseVector> data;
	unsigned char acu, c_x, c_y, c_velx, c_vely;
	float x, y, delta;

	acu = 0;
	pb.Get(&c_x, bit_len(acu, rec_range_exp));/// x,y of vector
	pb.Get(&c_y, bit_len(acu, rec_range_exp));
	
	pb.Get(&c_vely, CAudio_vel_angle_bits);
	pb.Get(&c_velx, CAudio_vel_length_bits);

	HearBallController(CAudio_Invalid_Num);

#ifndef _LONG_AUDIO
	if(!IsFullRange(rec_range_exp) && 
		(!ball.IsValidObject() 
			|| ball.pos_delta > Max_ref_delta(rec_range_exp)))
	{
		//can't utilize heard info for insufficient reference accuracy.
		DoRecord(LOG_HEAR, "abort hear ball");
		return;
	}
#endif
//parse pos data
	x = c2f_x(c_x, acu, rec_range_exp, ball.pos.x);
	y = c2f_y(c_y, acu, rec_range_exp, ball.pos.y);
	delta = accuracy_2_delta(acu);
	delta += Quantize_delta(acu);
	data.Setdata(NoiseVector(x, y, delta), parse_time);
	HearBallPos(data);
//parse vel data
	data.data.delta = acu;
	data.data.mean = Polar2Vector(c_velx * CAudio_vel_length_grain, 
				c_vely * CAudio_vel_angle_grain);
	HearBallVel(data);
}

void CBitAuditory::ParseMsg_Player(CParseBit& pb, int no){
	TimedData<NoiseVector> data;
	unsigned char acu, c_x, c_y;
	float x, y, delta;
	pb.Get(&acu, CAudio_accuracy_bits);// 2 bits specify the vector accuracy
	pb.Get(&c_x, bit_len(acu, rec_range_exp));/// x,y of vector
	pb.Get(&c_y, bit_len(acu, rec_range_exp));

	Player* p = &GetPlayer(no);

#ifndef _LONG_AUDIO
	if(!IsFullRange(rec_range_exp) && 
		(!p->IsValidObject() || p->pos_delta > Max_ref_delta(rec_range_exp))){
		DoRecord(LOG_HEAR, "abort hear %d", no);
		//can't utilize heard info for insufficient reference accuracy.
		return;
	}
#endif
	x = c2f_x(c_x, acu, rec_range_exp, p->pos.x);
	y = c2f_y(c_y, acu, rec_range_exp, p->pos.y);
	delta = accuracy_2_delta(acu);
	delta += Quantize_delta(acu);
	data.Setdata(NoiseVector(x, y, delta), parse_time);
	HearPlayerPos(data, no);
}

void CBitAuditory::ProcessMsg(char * auditorymsg, int speaker, int time){
	CParseBit pb;
	unsigned char c;
	pb.LoadFromChar(auditorymsg);
	//suspended for poor server
	//pb.Load((unsigned char* )auditorymsg,10);

	parse_time = time - 1;
	heard_my_side = SideSpeak(speaker, parse_time);
#ifdef Version7_Compatible
	if(ServerParam::version < 8.0f){		
		pb.Get(&c,1);	///the first bit is reserved for future ussage
		pb.Get(&c,1);	//get say time
		if(parse_time%2 != c) parse_time++;
		heard_my_side = 1;
	}
#endif 

	rec_hear_info.Setdata(speaker, parse_time);

	while(pb.Get(&c, CAudio_type_bits)){	//get info type
		if (c==CAudio_end) break;	//no more massage

		if(c == CAudio_ball){
			ParseMsg_Ball(pb);
		}else if(c == CAudio_pass){
			ParseMsg_Pass(pb);
		}else if(c == CAudio_Ctrl){
			ParseMsg_Ctrl(pb, speaker);
		}else if(0 < c && c <= SP_team_size){
			//normal player, side is heard_my_side
			if(!heard_my_side){
				c += SP_team_size;
			}
			ParseMsg_Player(pb, c);
		}else if(c == CAudio_extend){
			ParseMsg_Extend(pb);
		}
	}
}

void CBitAuditory::ParseMsg_Extend(CParseBit& pb){
	unsigned char c;
	if(pb.Get(&c, CAudio_type_bits)){
		if(0 < c && c <= SP_team_size){
			//extend player, side is !heard_my_side
			if(heard_my_side){
				c += SP_team_size;
			}
			ParseMsg_Player(pb, c);
		}
	}
}

void CBitAuditory::HearBallPos(TimedData<NoiseVector>& data){
	ball.Parse_HearPos(data); 
}

void CBitAuditory::HearBallVel(TimedData<NoiseVector>& data){
	ball.Parse_HearVel(data);
}

void CBitAuditory::HearPlayerPos(TimedData<NoiseVector>& data, int No){
	if(No != Agent::MyNumber){
		GetPlayer(No).Parse_HearPos(data);
	}
}

void CBitAuditory::HearPass(int time){
	ball.heardpass = TimedData<bool>(true, time);
}

/*add pos data*/
void CBitAuditory::AddPosMsg(CParseBit& pb, float x, float y, unsigned char acu){	
	unsigned char c;

	c = f2c_x(x, acu, range_exp);
	pb.Add(&c, bit_len(acu, range_exp));
	c = f2c_y(y, acu, range_exp);
	pb.Add(&c, bit_len(acu, range_exp));
}

//add vel data
void CBitAuditory::AddVelMsg(CParseBit& pb, unsigned char time_delay, const Vector& vel){
	unsigned char c;

	c = (unsigned char) (NormalizeAngle(vel.Angle(), 0) / CAudio_vel_angle_grain);
	pb.Add(&c, CAudio_vel_angle_bits);
	c = (unsigned char) (vel.mod() / CAudio_vel_length_grain);
	pb.Add(&c, CAudio_vel_length_bits);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -