pico neo3,unity 2021开发,讯飞语音测评unity SDK,用户射线点击UI面板录音按钮对单词录音,自动检测录音状态,同步显示录音可视化,如波状图,录音结束显示测评分数UI,回放录音,重录功能。对应脚本和unity事件的绑定,讯飞语音测评sdk与unity功能的接入、申请讯飞语音API接口的步骤。请分别给出具体详细步骤和对应脚本C#的完整实例。
时间: 2023-08-05 17:03:27 浏览: 263
这是一个比较复杂的项目,需要涉及到讯飞语音测评SDK的接入和使用,以及UI面板录音、波状图可视化、录音状态检测等功能的开发。以下是一个大致的实现步骤及对应脚本C#的完整实例:
1. 讯飞语音测评SDK的接入和使用
(1)首先,需要在讯飞开发者平台上注册账号,并创建应用,获取AppID和API Key。
(2)然后在Unity中导入讯飞语音测评SDK,并在项目中创建一个讯飞语音测评的管理类,用于初始化SDK和进行测评操作。
```csharp
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnitySpeechToText.Utilities;
namespace UnitySpeechToText.Services
{
public class IFlytekSpeechEvaluator : MonoBehaviour
{
public string appID = "yourAppID";
public string APIKey = "yourAPIKey";
private GameObject recordButton;
private GameObject playButton;
private GameObject stopButton;
private float[,] waveData;
private int recordLength = 0;
private int recordPosition = 0;
private AudioClip recordClip;
private bool isRecording = false;
private bool isPlaying = false;
private bool isStopped = false;
private float startTime;
private float endTime;
private AudioSource audioSource;
private string tempPath;
private string audioFilePath;
private string audioFileName;
private string resultFilePath;
private string resultFileName;
private string resultText;
private string errorText;
private bool hasResult = false;
private bool hasError = false;
private bool isInitialized = false;
private bool isRecordingAllowed = true;
private bool isPlayingAllowed = true;
private bool isStoppingAllowed = true;
private bool isEvaluatingAllowed = false;
private bool isDebugMode = false;
private bool isDebugLogEnabled = false;
private bool isDebugFileEnabled = false;
private bool isDebugEnabled = false;
private bool isInitializedDebug = false;
private bool isRecordingAllowedDebug = true;
private bool isPlayingAllowedDebug = true;
private bool isStoppingAllowedDebug = true;
private bool isEvaluatingAllowedDebug = false;
private bool isDebugModeDebug = false;
private bool isDebugLogEnabledDebug = false;
private bool isDebugFileEnabledDebug = false;
private bool isDebugEnabledDebug = false;
private Dictionary<string, string> parameters;
public UnityEvent OnStartRecording;
public UnityEvent OnStopRecording;
public UnityEvent OnStartPlaying;
public UnityEvent OnStopPlaying;
public UnityEvent OnStartEvaluating;
public UnityEvent OnStopEvaluating;
public UnityEvent OnResultReceived;
public UnityEvent OnErrorReceived;
public UnityEvent OnDebugModeChanged;
public UnityEvent OnDebugLogEnabledChanged;
public UnityEvent OnDebugFileEnabledChanged;
public UnityEvent OnResultFilePathChanged;
public UnityEvent OnErrorTextChanged;
public UnityEvent OnIsInitializedChanged;
public UnityEvent OnIsRecordingAllowedChanged;
public UnityEvent OnIsPlayingAllowedChanged;
public UnityEvent OnIsStoppingAllowedChanged;
public UnityEvent OnIsEvaluatingAllowedChanged;
public UnityEvent OnWaveDataChanged;
public UnityEvent OnRecordPositionChanged;
public UnityEvent OnRecordLengthChanged;
public UnityEvent OnIsRecordingChanged;
public UnityEvent OnIsPlayingChanged;
public UnityEvent OnIsStoppedChanged;
public UnityEvent OnStartTimeChanged;
public UnityEvent OnEndTimeChanged;
}
}
```
(3)接着,在管理类中实现初始化SDK和测评操作的方法。初始化SDK方法需要在Start()函数中调用。
```csharp
public void Start()
{
InitSpeechEvaluator();
}
private void InitSpeechEvaluator()
{
if (string.IsNullOrEmpty(appID) || string.IsNullOrEmpty(APIKey))
{
Debug.LogError("Please specify AppID and APIKey in the Inspector.");
return;
}
if (audioSource == null)
{
audioSource = gameObject.AddComponent<AudioSource>();
}
if (!Directory.Exists(tempPath))
{
Directory.CreateDirectory(tempPath);
}
if (isDebugMode)
{
Debug.Log("Initializing Speech Evaluator...");
}
// Initialize the Speech Evaluator
SpeechEvaluator.Instance.Init(appID, APIKey);
// Set the Callbacks
SpeechEvaluator.Instance.OnResultReceived += OnResultReceivedHandler;
SpeechEvaluator.Instance.OnErrorReceived += OnErrorReceivedHandler;
isInitialized = true;
if (isDebugMode)
{
Debug.Log("Speech Evaluator Initialized.");
}
}
public void Evaluate(string text)
{
if (!isInitialized || !isEvaluatingAllowed)
{
return;
}
if (isDebugMode)
{
Debug.Log("Evaluating Speech...");
}
// Start Recording
StartRecording();
// Play the Text to Evaluate
SpeechEvaluator.Instance.Evaluate(text);
// Stop Recording
StopRecording();
}
```
2. UI面板录音、波状图可视化、录音状态检测等功能的开发
(1)添加按钮和文本框
在Unity中创建一个Canvas,然后在Canvas中添加一个Button和一个Text,用于实现录音和显示分数的功能。将Button命名为RecordButton,将Text命名为ScoreText。
(2)添加录音和波状图可视化的脚本
在Canvas上添加一个新的脚本,用于实现录音和波状图可视化的功能。以下是该脚本的主要代码:
```csharp
using UnityEngine;
using UnityEngine.UI;
public class RecordAndVisualize : MonoBehaviour
{
public Button recordButton;
public Text scoreText;
public AudioSource audioSource;
public Image waveImage;
public int waveSamples = 1024;
public float waveHeight = 100f;
public Color waveColor = Color.white;
public Color backgroundColor = Color.black;
public float waveUpdateTime = 0.1f;
public float silenceThreshold = 0.001f;
public float silenceDuration = 0.5f;
public bool isRecording = false;
public bool isPlaying = false;
public bool isStopped = false;
private float[] waveData;
private int wavePosition = 0;
private float startTime;
private float endTime;
private AudioClip recordClip;
private string audioFileName;
private string resultFileName;
private string resultText;
private float silenceStart = 0f;
private float lastUpdateTime = 0f;
void Start()
{
recordButton.onClick.AddListener(OnRecordButtonClick);
}
void Update()
{
if (isRecording)
{
Record();
}
else if (isPlaying)
{
Play();
}
else if (isStopped)
{
Stop();
}
else
{
UpdateWaveImage();
}
}
void OnRecordButtonClick()
{
if (!isRecording)
{
StartRecording();
}
else
{
StopRecording();
}
}
void StartRecording()
{
isRecording = true;
startTime = Time.time;
audioFileName = "audio_" + startTime.ToString("yyyyMMddHHmmss") + ".wav";
resultFileName = "result_" + startTime.ToString("yyyyMMddHHmmss") + ".txt";
recordClip = Microphone.Start(null, false, 10, 44100);
waveData = new float[waveSamples];
UpdateWaveImage();
}
void StopRecording()
{
isRecording = false;
Microphone.End(null);
waveData = null;
UpdateWaveImage();
Evaluate();
}
void Record()
{
int samplePosition = Microphone.GetPosition(null);
float[] samples = new float[recordClip.samples * recordClip.channels];
recordClip.GetData(samples, 0);
for (int i = 0; i < waveSamples && wavePosition < recordClip.samples; i++, wavePosition++)
{
waveData[i] = samples[wavePosition];
}
UpdateWaveImage();
}
void Play()
{
if (Time.time - lastUpdateTime >= waveUpdateTime)
{
lastUpdateTime = Time.time;
UpdateWaveImage();
}
}
void Stop()
{
waveData = null;
UpdateWaveImage();
}
void UpdateWaveImage()
{
if (waveImage != null)
{
waveImage.color = backgroundColor;
waveImage.fillAmount = 1f;
if (waveData != null)
{
float[] fft = SpeechToTextUtils.CalculateFFT(waveData);
float[] spectrum = SpeechToTextUtils.GetSpectrum(fft, waveSamples, audioSource.clip.frequency);
for (int i = 0; i < waveSamples; i++)
{
float x = (float)i / waveSamples;
float y = waveHeight * spectrum[i];
waveImage.rectTransform.SetInsetAndSizeFromParentEdge(RectTransform.Edge.Left, x * waveImage.rectTransform.rect.width, 1f);
waveImage.rectTransform.SetInsetAndSizeFromParentEdge(RectTransform.Edge.Top, waveHeight / 2f - y / 2f, y);
waveImage.color = waveColor;
}
}
}
}
void Evaluate()
{
string audioFilePath = Application.persistentDataPath + "/" + audioFileName;
string resultFilePath = Application.persistentDataPath + "/" + resultFileName;
File.WriteAllBytes(audioFilePath, WavUtility.FromAudioClip(recordClip));
StartCoroutine(SpeechEvaluator.Instance.Evaluate(audioFilePath, resultFilePath, OnResultReceived, OnErrorReceived));
}
void OnResultReceived(string result)
{
resultText = result;
scoreText.text = resultText;
}
void OnErrorReceived(string error)
{
Debug.LogError(error);
}
}
```
(3)添加录音状态检测的脚本
在Canvas上添加一个新的脚本,用于实现录音状态检测的功能。以下是该脚本的主要代码:
```csharp
using UnityEngine;
using UnityEngine.UI;
public class RecordStatus : MonoBehaviour
{
public Image statusImage;
public Color recordingColor = Color.red;
public Color playingColor = Color.green;
public Color stoppedColor = Color.gray;
public float blinkTime = 0.5f;
public bool isRecording = false;
public bool isPlaying = false;
public bool isStopped = false;
private float lastBlinkTime = 0f;
void Update()
{
if (isRecording)
{
statusImage.color = recordingColor;
}
else if (isPlaying)
{
statusImage.color = playingColor;
}
else if (isStopped)
{
statusImage.color = stoppedColor;
}
else
{
statusImage.color = Color.white;
}
if ((isRecording || isPlaying) && Time.time - lastBlinkTime >= blinkTime)
{
lastBlinkTime = Time.time;
statusImage.enabled = !statusImage.enabled;
}
}
}
```
3. 对应脚本和Unity事件的绑定
将RecordAndVisualize脚本中的recordButton属性和RecordStatus脚本中的statusImage属性分别与对应的Button和Image对象绑定,然后在Unity中添加OnClick事件,并将RecordAndVisualize脚本中的OnRecordButtonClick方法绑定到OnClick事件中。
4. 申请讯飞语音API接口的步骤
(1)访问讯飞开放平台,注册账号并登录。
(2)创建新应用,获取AppID和API Key。
(3)在应用管理页面中开通语音评测服务。
(4)在代码中使用AppID和API Key进行身份验证,并调用讯飞语音测评SDK的相关接口实现功能。
阅读全文