ict.lixian.single/Assets/Scripts/cxx/MicrophoneInput.cs

338 lines
8.8 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using UnityEngine.Networking;
using System.Text;
using System.Security.Cryptography;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using UnityEngine.UI;
public class MicrophoneInput : MonoBehaviour
{
public static MicrophoneInput instance;
public AudioSource audioSource;
/// <summary>
/// 最大录音时长
/// </summary>
public int lengthSec = 30;
/// <summary>
/// 采样频率
/// </summary>
private int frequency = 16000;
private string savePath;
/// <summary>
/// 录音时长
/// </summary>
public float recordTime;
private void Awake()
{
instance = this;
savePath = Application.persistentDataPath + "/audios/micro.wav";
audioSource = gameObject.AddComponent<AudioSource>();
audioSource.playOnAwake = false;
if (!Directory.Exists(Path.GetDirectoryName(savePath)))
{
Directory.CreateDirectory(Path.GetDirectoryName(savePath));
}
if (!File.Exists(savePath))
{
File.Create(savePath);
}
}
private void Update()
{
if (Microphone.IsRecording(null))
{
recordTime += Time.deltaTime;
}
}
/// <summary>
/// 检查录音权限,并开始录制
/// </summary>
[ContextMenu("开始录音")]
public void OnStartClick()
{
Debug.Log("OnStartClick");
if (!CheckMicrophone())
{
Debug.LogError("无录音权限,获取中,请重新说话");
MyDebugger.Log("无录音权限,获取中,请重新说话");
StartCoroutine(RequestMicrophoneAuth());
return;
}
StartRecord();
}
/// <summary>
/// 检测麦克风
/// </summary>
/// <returns></returns>
public bool CheckMicrophone()
{
return Application.HasUserAuthorization(UserAuthorization.Microphone);
}
[ContextMenu("结束录音,开始识别")]
public void MyStop()
{
OnStopClick(str =>
{
Debug.Log("识别完成: "+str);
});
}
/// <summary>
/// 停止录制,并转文字
/// </summary>
public void OnStopClick(Action<string> callback)
{
Debug.Log("OnStopClick");
int length = StopRecord();
Debug.Log("录音返回长度:" + length);
if (length > 0)
{
TransToText(callback);
}
else
{
MyDebugger.Log("没录音数据");
}
}
/// <summary>
/// 播放录音
/// </summary>
public void PlayAudio()
{
//读取本地文件播放
ReadAudioFile(savePath);
}
public IEnumerator RequestMicrophoneAuth()
{
yield return Application.RequestUserAuthorization(UserAuthorization.Microphone);
}
private void StartRecord()
{
if (Microphone.devices.Length > 0)
{
if (!Microphone.IsRecording(null))
{
Debug.Log("开始录音");
audioSource.Stop();
audioSource.loop = false;
audioSource.mute = true;
audioSource.clip = Microphone.Start(null, false, lengthSec, frequency);
MyDebugger.Log("录音中");
recordTime = 0;
}
else
{
Debug.Log("当前正在录音,请先停止录音");
}
}
else
{
Debug.Log("无麦克风");
MyDebugger.Log("无麦克风");
}
}
/// <summary>
/// 单纯停止录音
/// </summary>
/// <returns></returns>
public int StopRecord()
{
int length = Microphone.GetPosition(null);
Microphone.End(null);
return length;
}
public void TransToText(Action<string> callback)
{
if (audioSource.clip != null && audioSource.clip.length > 0)
{
byte[] file = WavUtility.FromAudioClip(audioSource.clip, savePath, true);
Debug.Log("TransToText长度" + file.Length); ;
IFlytekManager.instance.AudioToText(file, str =>
{
callback(str);
});
}
}
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);
}
}