ict.lixian.single/Assets/Scripts/kdl/MicrophoneInputHuman.cs

274 lines
7.1 KiB
C#

using System;
using System.Collections;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using UnityEngine;
public class MicrophoneInputHuman : MonoBehaviour
{
public static MicrophoneInputHuman instance;
public AudioSource audioSource;
public int lengthSec = 60;
private int frequency = 16000;
private string savePath;
private void Awake()
{
instance = this;
savePath = Application.persistentDataPath + "/audios/micro.wav";
audioSource = GetComponent<AudioSource>();
if (!Directory.Exists(Path.GetDirectoryName(savePath)))
{
Directory.CreateDirectory(Path.GetDirectoryName(savePath));
}
if (!File.Exists(savePath))
{
File.Create(savePath);
}
}
/// <summary>
/// 开始录制
/// </summary>
public void OnStartClick()
{
Debug.Log("OnStartClick");
if (!Application.HasUserAuthorization(UserAuthorization.Microphone))
{
Debug.LogError("无录音权限,获取中,请重新说话");
MyDebugger.Log("无录音权限,获取中,请重新说话");
StartCoroutine(RequestMicrophoneAuth());
return;
}
StartRecord();
}
/// <summary>
/// 停止录制
/// </summary>
public void OnStopClick(Action<string> callback)
{
Debug.Log("OnStopClick");
int length = StopRecord();
if (length > 0)
{
byte[] file = WavUtility.FromAudioClip(audioSource.clip, savePath, true);
IFlytekManager.instance.AudioToText(file, str =>
{
callback(str);
});
}
else
{
MyDebugger.Log("没录音数据");
}
}
/// <summary>
/// 播放录音
/// </summary>
private void PlayAudio()
{
//读取本地文件播放
ReadAudioFile(savePath);
}
public IEnumerator RequestMicrophoneAuth()
{
yield return Application.RequestUserAuthorization(UserAuthorization.Microphone);
}
public void StartRecord()
{
if (Microphone.devices.Length > 0)
{
Debug.Log("开始录音");
audioSource.Stop();
audioSource.loop = false;
audioSource.mute = true;
audioSource.clip = Microphone.Start(null, false, lengthSec, frequency);
MyDebugger.Log("录音中");
}
else
{
Debug.Log("无麦克风");
MyDebugger.Log("无麦克风");
}
}
public int StopRecord()
{
int length = Microphone.GetPosition(null);
Microphone.End(null);
return length;
}
public bool SaveAudioFile(string filePath, int length)
{
if (Microphone.IsRecording(null))
return false;
byte[] data = GetClipData(audioSource, length);
if (data == null)
{
return false;
}
File.WriteAllBytes(filePath, data);
string infoLog = "total length:" + data.Length + " time:" + audioSource.time + " path:" + filePath;
Debug.Log(infoLog);
return true;
}
public void ReadAudioFile(string filePath)
{
byte[] bytes = File.ReadAllBytes(filePath);
float[] samples = byte2float(bytes);
var clip = audioSource.clip;
audioSource.Stop();
audioSource.clip = AudioClip.Create(clip.name, samples.Length, clip.channels, clip.frequency, false);
audioSource.clip.SetData(samples, 0);
audioSource.mute = false;
audioSource.Play();
}
byte[] GetClipData(AudioSource source, int length)
{
if (length < 10)
{
Debug.Log("录音文件太短");
return null;
}
float[] samples = new float[length];
source.clip.GetData(samples, 0);
byte[] outData = float2byte(samples);
return outData;
}
byte[] float2byte(float[] floats)
{
byte[] outData = new byte[floats.Length * 2];
int reScaleFactor = 32767;
for (int i = 0; i < floats.Length; i++)
{
short tempShort = (short)(floats[i] * reScaleFactor);
byte[] tempData = BitConverter.GetBytes(tempShort);
outData[i * 2] = tempData[0];
outData[i * 2 + 1] = tempData[1];
}
return outData;
}
float[] byte2float(byte[] bytes)
{
float reScaleFactor = 32768.0f;
float[] data = new float[bytes.Length / 2];
for (int i = 0; i < bytes.Length; i += 2)
{
short s;
if (BitConverter.IsLittleEndian) //小端和大端顺序要调整
s = (short)((bytes[i + 1] << 8) | bytes[i]);
else
s = (short)((bytes[i] << 8) | bytes[i + 1]);
// convert to range from -1 to (just below) 1
data[i / 2] = s / reScaleFactor;
}
return data;
}
//private IEnumerator CallAudioToString(string fileName,long fileSize)
//{
// string ts = GetTimeStampSecond().ToString();
// var a = new { duration = 200, fileName = fileName, fileSize = fileSize, signa = GetSigna(ts), ts = ts, appId = APPID };
// UnityWebRequest request = UnityWebRequest.Post("https://raasr.xfyun.cn/v2/api/upload", JsonConvert.SerializeObject(a));
// request.uploadHandler.contentType = "application/json";
// yield return request.SendWebRequest();
// if(!request.isNetworkError && !request.isHttpError)
// {
// Debug.Log(request.downloadHandler.text);
// audioText.text = request.downloadHandler.text;
// }
// else
// {
// audioText.text = request.downloadHandler.error;
// }
//}
//private string GetSigna(string ts)
//{
// string md5str = MD5(APPID + ts);
// string hmacStr= HMACSHA1Text(md5str, SecretKey);
// return hmacStr;
//}
/// <summary>
/// 获取时间戳-单位秒
/// </summary>
/// <returns></returns>
private int GetTimeStampSecond()
{
TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
return Convert.ToInt32(ts.TotalSeconds);
}
/// <summary>
/// 字符串MD5加密
/// </summary>
/// <param name="Text">要加密的字符串</param>
/// <returns>密文</returns>
private string MD5(string Text)
{
byte[] buffer = Encoding.UTF8.GetBytes(Text);
System.Security.Cryptography.MD5CryptoServiceProvider check;
check = new System.Security.Cryptography.MD5CryptoServiceProvider();
byte[] somme = check.ComputeHash(buffer);
string ret = "";
foreach (byte a in somme)
{
if (a < 16)
ret += "0" + a.ToString("X");
else
ret += a.ToString("X");
}
return ret.ToLower();
}
private string HMACSHA1Text(string text, string key)
{
//HMACSHA1加密
HMACSHA1 hmacsha1 = new HMACSHA1();
hmacsha1.Key = Encoding.UTF8.GetBytes(key);
byte[] dataBuffer = Encoding.UTF8.GetBytes(text);
byte[] hashBytes = hmacsha1.ComputeHash(dataBuffer);
return Convert.ToBase64String(hashBytes);
}
}