private int GetNextParamOffset(byte[] data, TcpLogHeader header, LogParamId logParamId, ref int paramIdOffset) { int paramId = 0; int dataSize = 0; paramId = LoadBigEndianUInt16(data, paramIdOffset); if (header.isPtr64 == true) { dataSize = CriProfiler.LogParams[paramId].size64; } else { dataSize = CriProfiler.LogParams[paramId].size32; } if (CriProfiler.LogParams[paramId].type == LogParamTypes.TYPE_CHAR) { dataSize += LoadBigEndianUInt16(data, paramIdOffset + paramIdSize); } /* set parameter id offset */ paramIdOffset += paramIdSize + dataSize; if ((LogParamId)LoadBigEndianUInt16(data, paramIdOffset) != logParamId) { throw new ParamIdDoesNotMatchException("Parsed parameter ID does not match with " + logParamId.ToString()); } /* return parameter data offset */ return(paramIdOffset + paramIdSize); }
private int FindParamOffset(byte[] data, TcpLogHeader header, LogParamId logParamId, out int currentOffset) { if (data.Length < TcpLogHeader.properSize) { throw new ParamIdDoesNotMatchException("Could not find parameter: " + logParamId.ToString()); } int offset = header.size; int paramId; int dataSize; while (offset < header.packetSize) { paramId = LoadBigEndianUInt16(data, offset); if ((LogParamId)paramId == logParamId) { currentOffset = offset; return(offset + paramIdSize); } dataSize = header.isPtr64 ? LogParams[paramId].size64 : LogParams[paramId].size32; if (LogParams[paramId].type == LogParamTypes.TYPE_CHAR) { dataSize += LoadBigEndianUInt16(data, offset + paramIdSize); } offset += paramIdSize + dataSize; } throw new ParamIdDoesNotMatchException("Could not find parameter: " + logParamId.ToString()); }
private int GetStrDataOffset(TcpLogHeader header, int paramIdOffset) { if (header.isPtr64 == true) { return(paramIdOffset + CriProfiler.paramIdSize + ParamTypeSizes64[(int)CriProfiler.LogParamTypes.TYPE_CHAR]); } else { return(paramIdOffset + CriProfiler.paramIdSize + ParamTypeSizes32[(int)CriProfiler.LogParamTypes.TYPE_CHAR]); } }
private int GetFirstParamOffset(byte[] data, TcpLogHeader header, LogParamId logParamId, out int paramIdOffset) { /* set parameter id offset */ paramIdOffset = header.size; if ((LogParamId)LoadBigEndianUInt16(data, paramIdOffset) != logParamId) { throw new ParamIdDoesNotMatchException("Parsed parameter ID does not match with " + logParamId.ToString()); } /* return parameter data offset */ return(paramIdOffset + CriProfiler.paramIdSize); }
/** * Override this method to add new parsing procedure */ protected virtual void UserDefinedParser(byte[] data, TcpLogHeader packetHeader) { /** e.g. * int offset; * switch ((TcpCommandId)packetHeader.command) { * case TcpCommandId.<CRITCP_MAIL_xxx>: * switch (GetLogFuncId(packetHeader.function_id)) { * case LogFuncId.<LOG_COMMAND_xxx>: * <parsing> * break; * default: * break; * } * break; * default: * break; * } */ }
private int GetNextParamOffset(byte[] data, TcpLogHeader header, LogParamId logParamId, ref int currentOffset) { if (currentOffset >= header.packetSize) { throw new ParamIdDoesNotMatchException("Could not find parameter: " + logParamId.ToString()); } int paramId = LoadBigEndianUInt16(data, currentOffset); int dataSize = header.isPtr64 ? CriProfiler.LogParams[paramId].size64 : CriProfiler.LogParams[paramId].size32; if (CriProfiler.LogParams[paramId].type == LogParamTypes.TYPE_CHAR) { dataSize += LoadBigEndianUInt16(data, currentOffset + paramIdSize); } /* set parameter id offset */ currentOffset += paramIdSize + dataSize; if ((LogParamId)LoadBigEndianUInt16(data, currentOffset) != logParamId) { throw new ParamIdDoesNotMatchException("Parsed parameter ID does not match with " + logParamId.ToString()); } /* return parameter data offset */ return(currentOffset + paramIdSize); }
/** * Override this method to rewrite the whole parsing procedure */ protected virtual void Parser(byte[] data, TcpLogHeader packetHeader) { int offset = 0; int dataSize = 0; UInt32 playbackId; StreamTypes streamType; VoicePoolInfo voicePoolInfo; UInt64 voicePoolHn; Single levelPeak; Single levelRms; Single levelPeakHold; int numCh = 0; int numOutputCh; int numMaxCh = 0; switch ((TcpCommandId)packetHeader.command) { case TcpCommandId.CRITCP_MAIL_PREVIEW_CPU_LOAD: if (GetLogFuncId(packetHeader.function_id) == LogFuncId.LOG_COMMAND_CpuLoadAndNumUsedVoices) { this.cpu_load = LoadBigEndianSingle(data, GetFirstParamOffset(data, packetHeader, LogParamId.LOG_STRINGS_ITEM_CpuLoad, out offset)); this.num_used_voices = LoadBigEndianUInt32(data, GetNextParamOffset(data, packetHeader, LogParamId.LOG_STRINGS_ITEM_NumUsedVoices, ref offset)); lock (cpuLoadHistory) { cpuLoadHistory.EnBuffer(new Single[] { cpu_load }, 1); } lock (voiceUsageHistory) { voiceUsageHistory.EnBuffer(new UInt32[] { num_used_voices }, 1); } break; } break; case TcpCommandId.CRITCP_MAIL_SEND_LOG: switch (GetLogFuncId(packetHeader.function_id)) { case LogFuncId.LOG_COMMAND_LoudnessInfo: this.loudness_momentary = LoadBigEndianSingle(data, GetFirstParamOffset(data, packetHeader, LogParamId.LOG_STRINGS_ITEM_MomentaryValue, out offset)); this.loudness_shortTerm = LoadBigEndianSingle(data, GetNextParamOffset(data, packetHeader, LogParamId.LOG_STRINGS_ITEM_ShortTermValue, ref offset)); this.loudness_integrated = LoadBigEndianSingle(data, GetNextParamOffset(data, packetHeader, LogParamId.LOG_STRINGS_ITEM_IntegratedValue, ref offset)); break; case LogFuncId.LOG_COMMAND_StreamingInfo: this.num_used_streams = LoadBigEndianUInt32(data, GetFirstParamOffset(data, packetHeader, LogParamId.LOG_STRINGS_ITEM_NumUsedVoices, out offset)); this.total_bps = LoadBigEndianSingle(data, GetNextParamOffset(data, packetHeader, LogParamId.LOG_STRINGS_ITEM_TotalBps, ref offset)); break; case LogFuncId.LOG_COMMAND_AsrBusAnalyzeInfoAllCh: if (LoadBigEndianByte(data, GetFirstParamOffset(data, packetHeader, LogParamId.LOG_STRINGS_ITEM_BusNo, out offset)) == 0) /* if the bus is MasterOut(bus0) */ { numCh = LoadBigEndianByte(data, GetParamOffsetByOrder(data, packetHeader, LogParamId.LOG_STRINGS_ITEM_NumCh, 3, out offset)); lock (levels) { if (numMaxCh == 0) { numMaxCh = numCh; levels.Clear(); for (int i = 0; i < numMaxCh; ++i) { levels.Add(new LevelInfo(Mathf.NegativeInfinity, Mathf.NegativeInfinity, Mathf.NegativeInfinity)); } } if (numMaxCh == numCh) { for (int i = 0; i < numCh; ++i) { levelPeak = LoadBigEndianSingle(data, GetNextParamOffset(data, packetHeader, LogParamId.LOG_STRINGS_ITEM_PeakLevel, ref offset)); levelRms = LoadBigEndianSingle(data, GetNextParamOffset(data, packetHeader, LogParamId.LOG_STRINGS_ITEM_RmsLevel, ref offset)); levelPeakHold = LoadBigEndianSingle(data, GetNextParamOffset(data, packetHeader, LogParamId.LOG_STRINGS_ITEM_PeakHoldLevel, ref offset)); levels[i] = new LevelInfo(levelPeak, levelRms, levelPeakHold); } } } } break; case LogFuncId.LOG_COMMAND_ExStandardVoicePoolConfig: if (Convert.ToBoolean(LoadBigEndianByte(data, GetParamOffsetByOrder(data, packetHeader, LogParamId.LOG_STRINGS_ITEM_StreamingFlag, 5, out offset))) == false) { this.maxVoice_stdOnMemory = LoadBigEndianUInt32(data, GetParamOffsetByOrder(data, packetHeader, LogParamId.LOG_STRINGS_ITEM_NumVoices, 2, out offset)); } else { this.maxVoice_stdStreaming = LoadBigEndianUInt32(data, GetParamOffsetByOrder(data, packetHeader, LogParamId.LOG_STRINGS_ITEM_NumVoices, 2, out offset)); } break; case LogFuncId.LOG_COMMAND_ExHcaMxVoicePoolConfig: if (Convert.ToBoolean(LoadBigEndianByte(data, GetParamOffsetByOrder(data, packetHeader, LogParamId.LOG_STRINGS_ITEM_StreamingFlag, 5, out offset))) == false) { this.maxVoice_hcamxOnMemory = LoadBigEndianUInt32(data, GetParamOffsetByOrder(data, packetHeader, LogParamId.LOG_STRINGS_ITEM_NumVoices, 2, out offset)); } else { this.maxVoice_hcamxStreaming = LoadBigEndianUInt32(data, GetParamOffsetByOrder(data, packetHeader, LogParamId.LOG_STRINGS_ITEM_NumVoices, 2, out offset)); } break; case LogFuncId.LOG_COMMAND_ExVoicePoolHn: try { voicePoolHn = LoadBigEndianUInt64(data, GetFirstParamOffset(data, packetHeader, LogParamId.LOG_STRINGS_ITEM_ExVoicePoolHn, out offset)); voicePoolInfo = new VoicePoolInfo(LoadBigEndianUInt32(data, GetNextParamOffset(data, packetHeader, LogParamId.LOG_STRINGS_ITEM_SoundFormat, ref offset)), null); lock (voicePoolInfoTable) { voicePoolInfoTable.Add(voicePoolHn, voicePoolInfo); } } catch (ArgumentException) { /* Voice pool info already exists; Do nothing */ } break; case LogFuncId.LOG_COMMAND_ExVoicePool_Free: voicePoolHn = LoadBigEndianUInt64(data, GetFirstParamOffset(data, packetHeader, LogParamId.LOG_STRINGS_ITEM_ExVoicePoolHn, out offset)); lock (voicePoolInfoTable) { voicePoolInfoTable.Remove(voicePoolHn); } break; case LogFuncId.LOG_COMMAND_PlayerPool_NumVoices: voicePoolHn = LoadBigEndianUInt64(data, GetFirstParamOffset(data, packetHeader, LogParamId.LOG_STRINGS_ITEM_ExVoicePoolHn, out offset)); lock (voicePoolInfoTable) { if (voicePoolInfoTable[voicePoolHn] != null) { (voicePoolInfoTable[voicePoolHn] as VoicePoolInfo).numUsedVoices = (int)LoadBigEndianUInt32(data, GetNextParamOffset(data, packetHeader, LogParamId.LOG_STRINGS_ITEM_NumUsedVoices, ref offset)); } } break; case LogFuncId.LOG_COMMAND_ExPlaybackId: playbackId = LoadBigEndianUInt32(data, GetFirstParamOffset(data, packetHeader, LogParamId.LOG_STRINGS_ITEM_ExPlaybackId, out offset)); dataSize = LoadBigEndianUInt16(data, GetParamOffsetByOrder(data, packetHeader, LogParamId.LOG_STRINGS_ITEM_CueName, 5, out offset)); if (dataSize > 1) { this.cuename_lastPlayed = System.Text.Encoding.Default.GetString(data, GetStrDataOffset(packetHeader, offset), dataSize); try { lock (playbackHashtable) { this.playbackHashtable.Add(playbackId, new PlaybackInfo(playbackId, cuename_lastPlayed, packetHeader.time)); } } catch (ArgumentException) { /* Duplicated playback info received; Do nothing */ } } else { this.cuename_lastPlayed = ""; } break; case LogFuncId.LOG_COMMAND_SoundVoice_Allocate: playbackId = LoadBigEndianUInt32(data, GetParamOffsetByOrder(data, packetHeader, LogParamId.LOG_STRINGS_ITEM_ExPlaybackId, 2, out offset)); streamType = (StreamTypes)LoadBigEndianByte(data, GetParamOffsetByOrder(data, packetHeader, LogParamId.LOG_STRINGS_ITEM_StreamType, 5, out offset)); lock (playbackHashtable) { if (playbackHashtable.ContainsKey(playbackId)) { (playbackHashtable[playbackId] as PlaybackInfo).StreamType = (int)streamType; } } break; case LogFuncId.LOG_COMMAND_ExAsrConfig: numOutputCh = LoadBigEndianByte(data, GetParamOffsetByOrder(data, packetHeader, LogParamId.LOG_STRINGS_ITEM_OutputChannels, 2, out offset)); if (numOutputCh > this.numChMasterOut) { numChMasterOut = numOutputCh; } break; default: break; } break; case TcpCommandId.CRITCP_MAIL_MONITOR_ATOM_EXPLAYBACKINFO_PLAY_END: switch (GetLogFuncId(packetHeader.function_id)) { case LogFuncId.LOG_COMMAND_ExPlaybackInfo_FreeInfo: playbackId = LoadBigEndianUInt32(data, GetFirstParamOffset(data, packetHeader, LogParamId.LOG_STRINGS_ITEM_ExPlaybackId, out offset)); lock (playbackHashtable) { playbackHashtable.Remove(playbackId); } break; default: break; } break; default: UserDefinedParser(data, packetHeader); break; } }
/** * Sub thread task to extract TCP packets from the buffer. */ private void TaskPacketReading(int readIntervalMillisec) { Stopwatch stopwatch = new Stopwatch(); const int threadMaxLifeMs = 20000; /* should be longer than total TCP retrying time */ const int threadRetryLifeMs = 500; byte[] data = null; TcpLogHeader packetHeader; int packetSize = 0; stopwatch.Start(); while (true) { if (this.isBufferCorrupted == false) { lock (this.TcpBuffer) { packetSize = GetPacketSize(TcpBuffer); data = this.TcpBuffer.DeBuffer(packetSize); } if (data != null) { stopwatch.Reset(); stopwatch.Start(); packetHeader = new TcpLogHeader(data); try { if (packetHeader.size > 0) { this.Parser(data, packetHeader); } /* if headerSize > 0 */ } catch (Exception ex) { /* Any parsing error */ if (ex is ParamIdDoesNotMatchException) { UnityEngine.Debug.LogWarning("[CRIWARE] " + ex.Message.ToString()); } UnityEngine.Debug.LogWarning("[CRIWARE] (Profiler) Packet parsing failed: buffer may be corrupted. Reconstructing buffer..." + "\nLog Function: " + GetLogFuncId(packetHeader.function_id).ToString()); this.isBufferCorrupted = true; } } else { /* kill all threads if waited for too long */ if (this.isConnected == true) { if (stopwatch.ElapsedMilliseconds > threadRetryLifeMs) { this.isProfiling = false; threadTerminator.Set(); } } else { if (stopwatch.ElapsedMilliseconds > threadMaxLifeMs) { this.isProfiling = false; threadTerminator.Set(); } } } /* if data != null */ } /* if isBufferCorrupted == false */ if (threadTerminator.WaitOne(readIntervalMillisec)) { this.isProfiling = false; break; } } }