Callbackの中でnullのチェックが色々追加されている部分は、音声データが上手く受信できてないときに多数エラーが出たので追加した。きちんとデータが送られているなら必要ないかもしれない。
デバッグに処理にかかった時間を表示しているのは、jetson nano 側のFPSと比べて差異がないのを確認するため。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Robotics.ROSTCPConnector;
using UnityEngine.Rendering;
using VideoMsgMsg = RosMessageTypes.CppPubsub.VideoMsgMsg;
using System;
public class Subscriber : MonoBehaviour
{
private ROSConnection ros;
public string mTopicName = "topic";
public GameObject mTestScreenL;
public GameObject mTestScreenR;
Texture2D mTextureL;
Texture2D mTextureR;
Texture2D mRecievedTextureL;
AudioSource mAudioSource;
float mDebugStartTime;
// Start is called before the first frame update
void Start()
{
Debug.Log("Start");//スクリプトが開始されたことを確認
mDebugStartTime = Time.realtimeSinceStartup;
//テクスチャ表示先のオブジェクト
mTestScreenL = GameObject.Find("TestScreenL");
mTestScreenR = GameObject.Find("TestScreenR");
mTextureL = new Texture2D(640, 480);
mTextureR = new Texture2D(640, 480);
mAudioSource = GetComponent<AudioSource>();
if (mAudioSource == null)
{
// AudioSourceが見つからない場合、新しく追加する
mAudioSource = gameObject.AddComponent<AudioSource>();
}
//テクスチャをオブジェクトに設定
mTestScreenL.GetComponent<Renderer>().material.mainTexture = mTextureL;
mTestScreenR.GetComponent<Renderer>().material.mainTexture = mTextureR;
ROSConnection.GetOrCreateInstance().Subscribe<VideoMsgMsg>(mTopicName, Callback);
}
void Callback(VideoMsgMsg msg)
{
if (msg == null)
{
Debug.LogError("Received null message.");
return;
}
if (null != msg)
{
//ROS2側から受け取ったデータでテクスチャ更新
mTextureL.LoadImage(msg.img_data_l);
mTextureR.LoadImage(msg.img_data_r);
// int16[]データをUnityのAudioSourceにセット
if (null != msg.audio_data)
{
float[] audioData = ConvertInt16ToFloat(msg.audio_data);
//float[] audioData = GenerateSinWave(440.0f, 44100, 1.0f);
if (mAudioSource != null)
{
// Debug.Log("Audio source output device: " + mAudioSource.outputAudioMixerGroup.audioMixer.outputAudioMixerGroup.name);
mAudioSource.volume = 50;
if (null != audioData)
{
AudioClip audioClip = AudioClip.Create("Beep", audioData.Length, 2, 44100, false);
audioClip.SetData(audioData, 0);
if (mAudioSource.isPlaying)
{
mAudioSource.Stop();
}
// AudioSource に AudioClip をセットして再生
mAudioSource.clip = audioClip;
mAudioSource.clip.SetData(audioData, 0);
// オーディオ再生
mAudioSource.Play();
// 処理時間
float elapsedTime = Time.realtimeSinceStartup - mDebugStartTime;
mDebugStartTime = Time.realtimeSinceStartup;
Debug.Log("処理にかかった時間: " + elapsedTime + "秒");
}
}
}
}
}
private float[] ConvertInt16ToFloat(short[] int16Data)
{
// int16[]データをfloat[]に変換
float[] floatData = new float[int16Data.Length];
for (int i = 0; i < int16Data.Length; i++)
{
// print(int16Data[i]);
if (null != int16Data[i])
{
floatData[i] = int16Data[i] / 32768.0f; // 正規化
}
else
{
floatData[i] = 0;
}
}
return floatData;
}
// Update is called once per frame
float[] GenerateSinWave(float frequency, int sampleRate, float duration)
{
int numSamples = (int)(sampleRate * duration);
float[] samples = new float[numSamples];
float increment = frequency * 2.0f * Mathf.PI / sampleRate;
for (int i = 0; i < numSamples; i++)
{
samples[i] = Mathf.Sin(increment * i);
}
return samples;
}
}