由于项目需求,需要做个在Pico里录音和回放的功能,但没要求持久化存储,那么直接放内存里一次性;
最后使用Unity的Microphone类和AudioSource组件实现
UI部分根据代码建立即可,我这就随便建了一个很简单的


在做的过程中还是出现了一些bug
以下是优化完之后的代码,有兴趣的朋友可以在我的基础上再优化扩展
using UnityEngine;
using UnityEngine.Android;
using UnityEngine.UI;
using System.Collections;
public class OptimizedAudioRecorder : MonoBehaviour
{
[Header("UI References")]
public Button recordButton;
public Button stopRecordButton;
public Button playButton;
public Button stopPlayButton;
public Text durationText; // 显示当前设置的录音时长
public Text elapsedTimeText; // 显示已录音时长
public Text statusText;
[Header("Settings")]
public float minDuration = 1f; // 最小录音时长(秒)
public float maxDuration = 60f; // 最大录音时长(秒)
public float updateInterval = 0.1f; // 时长更新频率(秒)
private AudioSource audioSource;
private AudioClip recordedClip;
private bool isRecording = false;
private bool isPlaying = false;
private string microphoneDevice;
private float currentDuration = 10f; // 当前设置的录音时长
private float recordingStartTime; // 录音开始时间
private Coroutine recordingTimerCoroutine; // 录音计时协程
private Coroutine playbackTimerCoroutine; // 播放计时协程
private float actualRecordedDuration = 0f; // 实际录音时长
void Start()
{
audioSource = gameObject.AddComponent<AudioSource>();
audioSource.playOnAwake = false;
currentDuration = Mathf.Clamp(currentDuration, minDuration, maxDuration);
InitializeUI();
CheckMicrophonePermission();
if (Microphone.devices.Length > 0)
{
microphoneDevice = Microphone.devices[0];
statusText.text = "准备就绪";
}
else
{
statusText.text = "未检测到麦克风";
SetButtonsInteractable(false);
}
UpdateDurationDisplay();
}
/// <summary>
/// 初始化UI组件和事件监听
/// </summary>
void InitializeUI()
{
recordButton.onClick.AddListener(() => StartRecording(currentDuration));
stopRecordButton.onClick.AddListener(StopRecording);
playButton.onClick.AddListener(PlayRecording);
stopPlayButton.onClick.AddListener(StopPlayback);
stopRecordButton.interactable = false;
stopPlayButton.interactable = false;
playButton.interactable = false;
elapsedTimeText.text = "已录音: 0.0s";
}
/// <summary>
/// 检查并请求麦克风权限
/// </summary>
void CheckMicrophonePermission()
{
if (!Permission.HasUserAuthorizedPermission(Permission.Microphone))
{
Permission.RequestUserPermission(Permission.Microphone);
statusText.text = "请求麦克风权限...";
}
}
/// <summary>
/// 更新时长显示
/// </summary>
void UpdateDurationDisplay()
{
durationText.text = $"设置时长: {currentDuration:F1}秒";
}
/// <summary>
/// 开始录音
/// </summary>
/// <param name="duration">录音时长(秒)</param>
public void StartRecording(float duration)
{
if (isRecording) return;
if (!Permission.HasUserAuthorizedPermission(Permission.Microphone))
{
statusText.text = "麦克风权限未授予!";
return;
}
if (recordedClip != null)
{
Destroy(recordedClip);
recordedClip = null;
}
try
{
recordedClip = Microphone.Start(
microphoneDevice,
false,
Mathf.CeilToInt(duration),
44100
);
isRecording = true;
recordingStartTime = Time.time;
actualRecordedDuration = 0f;
if (recordingTimerCoroutine != null)
StopCoroutine(recordingTimerCoroutine);
recordingTimerCoroutine = StartCoroutine(UpdateRecordingTime());
statusText.text = $"录音中... (最长: {duration:F1}秒)";
recordButton.interactable = false;
stopRecordButton.interactable = true;
playButton.interactable = false;
stopPlayButton.interactable = false;
}
catch (System.Exception e)
{
statusText.text = $"录音启动失败: {e.Message}";
isRecording = false;
recordButton.interactable = true;
stopRecordButton.interactable = false;
}
}
/// <summary>
/// 停止录音
/// </summary>
public void StopRecording()
{
if (!isRecording) return;
try
{
Microphone.End(microphoneDevice);
isRecording = false;
if (recordingTimerCoroutine != null)
{
StopCoroutine(recordingTimerCoroutine);
recordingTimerCoroutine = null;
}
statusText.text = $"录音已停止 (实际: {actualRecordedDuration:F1}秒)";
recordButton.interactable = true;
stopRecordButton.interactable = false;
playButton.interactable = true;
elapsedTimeText.text = $"已录音: {actualRecordedDuration:F1}s";
}
catch (System.Exception e)
{
statusText.text = $"停止录音失败: {e.Message}";
}
}
/// <summary>
/// 播放录音
/// </summary>
public void PlayRecording()
{
if (recordedClip == null)
{
statusText.text = "没有可播放的录音";
return;
}
try
{
audioSource.Stop();
audioSource.clip = recordedClip;
audioSource.Play();
isPlaying = true;
if (playbackTimerCoroutine != null)
StopCoroutine(playbackTimerCoroutine);
playbackTimerCoroutine = StartCoroutine(UpdatePlaybackTime());
statusText.text = "播放中...";
playButton.interactable = false;
stopPlayButton.interactable = true;
recordButton.interactable = false;
}
catch (System.Exception e)
{
statusText.text = $"播放失败: {e.Message}";
}
}
/// <summary>
/// 停止播放
/// </summary>
public void StopPlayback()
{
if (!isPlaying) return;
try
{
audioSource.Stop();
isPlaying = false;
if (playbackTimerCoroutine != null)
{
StopCoroutine(playbackTimerCoroutine);
playbackTimerCoroutine = null;
}
statusText.text = "播放已停止";
}
catch (System.Exception e)
{
statusText.text = $"停止播放失败: {e.Message}";
}
finally
{
playButton.interactable = true;
stopPlayButton.interactable = false;
recordButton.interactable = true;
}
}
/// <summary>
/// 更新录音时长的协程
/// </summary>
private IEnumerator UpdateRecordingTime()
{
float startTime = Time.time;
while (isRecording)
{
float elapsedTime = Time.time - startTime;
actualRecordedDuration = elapsedTime;
Debug.Log(actualRecordedDuration);
elapsedTimeText.text = $"已录音: {elapsedTime:F1}s";
if (elapsedTime >= currentDuration)
{
StopRecording();
yield break;
}
yield return new WaitForSeconds(updateInterval);
}
}
/// <summary>
/// 更新播放进度的协程
/// </summary>
private IEnumerator UpdatePlaybackTime()
{
float startTime = Time.time;
float playbackDuration = actualRecordedDuration > 0 ? actualRecordedDuration : recordedClip.length;
while (isPlaying && audioSource.isPlaying)
{
float elapsedTime = Time.time - startTime;
elapsedTimeText.text = $"播放中: {elapsedTime:F1}s / {playbackDuration:F1}s";
// 检查是否播放完成
if (elapsedTime >= playbackDuration)
{
elapsedTimeText.text = $"播放中: {playbackDuration:F1}s / {playbackDuration:F1}s";
StopPlayback();
yield break;
}
yield return new WaitForSeconds(updateInterval);
}
// 如果播放被外部中断(如用户停止)
if (isPlaying)
{
StopPlayback();
}
}
/// <summary>
/// 设置按钮交互状态
/// </summary>
private void SetButtonsInteractable(bool state)
{
recordButton.interactable = state;
stopRecordButton.interactable = false;
playButton.interactable = false;
stopPlayButton.interactable = false;
}
void OnDestroy()
{
if (isRecording)
{
Microphone.End(microphoneDevice);
}
if (isPlaying)
{
audioSource.Stop();
}
if (recordedClip != null)
{
Destroy(recordedClip);
}
}
}
1448

被折叠的 条评论
为什么被折叠?



