📄 bitaudio.cpp
字号:
#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 + -