当前位置: 首页 > java >正文

Unity轻松实现麦克风录音与播放

文章目录

    • 概要
    • 录音,播放
    • 音频
    • 注意事项
    • 参考

概要

之前有想写一个音乐播放的器的音频功能,一直没做,最近突然想写,就写了

录音,播放

在语言模型中,编码器和解码器都是由一个个的 Transformer 组件拼接在一起形成的。、

 private bool micConnected = false;//麦克风是否连接private int minFreq, maxFreq;//最小和最大频率public AudioClip RecordedClip;//录音public AudioSource audioSource;//播放的音频public Text Infotxt;//提示信息public Text Adress;//音频保存地址private string fileName;//保存的文件名private byte[] data;private string microphoneName;private bool isPlayAudio;private int lastPosition;public Button startBtn, stopBtn,playBtn,saveBtn;void Start(){if (Microphone.devices.Length <= 0){Infotxt.text = "缺少麦克风设备!";}else{microphoneName = Microphone.devices[0].ToString();Infotxt.text = "设备名称为:" + microphoneName + "请点击Start开始录音!";micConnected = true;Microphone.GetDeviceCaps(microphoneName, out minFreq, out maxFreq);if (minFreq == 0 && maxFreq == 0){maxFreq = 44100;}}startBtn.onClick.AddListener(Begin);stopBtn.onClick.AddListener(Stop);playBtn.onClick.AddListener(Player);saveBtn.onClick.AddListener(Save);}private float[] NormalizeData(float[] input){float value=0;for (int i = 0; i < input.Length; i++){if (value < input[i]){value = input[i];}}Debug.Log("Max:"+value);for (int i = 0; i < input.Length; i++){input[i] = input[i] / value;}return input;}/// <summary>/// 开始录音/// </summary>public void Begin(){if (micConnected){if (!Microphone.IsRecording(null)){RecordedClip = Microphone.Start(microphoneName, false, 60, maxFreq);Infotxt.text = "开始录音!";isPlayAudio = true;}else{Infotxt.text = "正在录音中,请勿重复点击Start!";}}else{Infotxt.text = "请确认麦克风设备是否已连接!";}}/// <summary>/// 停止录音/// </summary>public void Stop(){data = GetRealAudio(ref RecordedClip);Microphone.End(null);Infotxt.text = "录音结束!";isPlayAudio = false;}/// <summary>/// 播放录音/// </summary>public void Player(){if (!Microphone.IsRecording(null)){audioSource.clip = RecordedClip;audioSource.Play();Infotxt.text = "正在播放录音!";}else{Infotxt.text = "正在录音中,请先停止录音!";}}/// <summary>/// 保存录音/// </summary>public void Save(){if (!Microphone.IsRecording(null)){fileName = DateTime.Now.ToString("yyyyMMddHHmmssffff");if (!fileName.ToLower().EndsWith(".wav")){//如果不是“.wav”格式的,加上后缀fileName += ".wav";}string path = Path.Combine(Application.persistentDataPath, fileName);//录音保存路径print(path);//输出路径Adress.text = path;using (FileStream fs = CreateEmpty(path)){fs.Write(data, 0, data.Length);WriteHeader(fs, RecordedClip); //wav文件头}}else{Infotxt.text = "正在录音中,请先停止录音!";}}/// <summary>/// 获取真正大小的录音/// </summary>/// <param name="recordedClip"></param>/// <returns></returns>public static byte[] GetRealAudio(ref AudioClip recordedClip){int position = Microphone.GetPosition(null);if (position <= 0 || position > recordedClip.samples){position = recordedClip.samples;}float[] soundata = new float[position * recordedClip.channels];recordedClip.GetData(soundata, 0);recordedClip = AudioClip.Create(recordedClip.name, position,recordedClip.channels, recordedClip.frequency, false);recordedClip.SetData(soundata, 0);int rescaleFactor = 32767;byte[] outData = new byte[soundata.Length * 2];for (int i = 0; i < soundata.Length; i++){short temshort = (short)(soundata[i] * rescaleFactor);byte[] temdata = BitConverter.GetBytes(temshort);outData[i * 2] = temdata[0];outData[i * 2 + 1] = temdata[1];}Debug.Log("position=" + position + "  outData.leng=" + outData.Length);return outData;}/// <summary>/// 写文件头/// </summary>/// <param name="stream"></param>/// <param name="clip"></param>public static void WriteHeader(FileStream stream, AudioClip clip){int hz = clip.frequency;int channels = clip.channels;int samples = clip.samples;stream.Seek(0, SeekOrigin.Begin);Byte[] riff = System.Text.Encoding.UTF8.GetBytes("RIFF");stream.Write(riff, 0, 4);Byte[] chunkSize = BitConverter.GetBytes(stream.Length - 8);stream.Write(chunkSize, 0, 4);Byte[] wave = System.Text.Encoding.UTF8.GetBytes("WAVE");stream.Write(wave, 0, 4);Byte[] fmt = System.Text.Encoding.UTF8.GetBytes("fmt ");stream.Write(fmt, 0, 4);Byte[] subChunk1 = BitConverter.GetBytes(16);stream.Write(subChunk1, 0, 4);UInt16 one = 1;Byte[] audioFormat = BitConverter.GetBytes(one);stream.Write(audioFormat, 0, 2);Byte[] numChannels = BitConverter.GetBytes(channels);stream.Write(numChannels, 0, 2);Byte[] sampleRate = BitConverter.GetBytes(hz);stream.Write(sampleRate, 0, 4);Byte[] byteRate = BitConverter.GetBytes(hz * channels * 2);stream.Write(byteRate, 0, 4);UInt16 blockAlign = (ushort)(channels * 2);stream.Write(BitConverter.GetBytes(blockAlign), 0, 2);UInt16 bps = 16;Byte[] bitsPerSample = BitConverter.GetBytes(bps);stream.Write(bitsPerSample, 0, 2);Byte[] datastring = System.Text.Encoding.UTF8.GetBytes("data");stream.Write(datastring, 0, 4);Byte[] subChunk2 = BitConverter.GetBytes(samples * channels * 2);stream.Write(subChunk2, 0, 4);}/// <summary>/// 创建wav格式文件头/// </summary>/// <param name="filepath"></param>/// <returns></returns>private FileStream CreateEmpty(string filepath){FileStream fileStream = new FileStream(filepath, FileMode.Create);byte emptyByte = new byte();for (int i = 0; i < 44; i++) //为wav文件头留出空间{fileStream.WriteByte(emptyByte);}return fileStream;}private void LoadPCM(string filePath){/*  // 读取PCM音频数据byte[] pcmData = System.IO.File.ReadAllBytes(filePath);*/// 转换PCM音频数据为浮点数数组float[] floatData = new float[data.Length / 2];for (int i = 0; i < floatData.Length; i++){floatData[i] = (float)System.BitConverter.ToInt16(data, i * 2) / 32768f;}// 创建AudioClip,参数说明:// pcmData:PCM音频数据// false:是否为压缩格式,默认为false// false:是否为3D音频,默认为false// AudioType.UNKNOWN:音频类型,根据实际情况选择合适的类型// 44100:采集最佳频率AudioClip audioClip = AudioClip.Create("PCM", data.Length / 2, 1, 44100, false);audioClip.SetData(floatData, 0);}

音频

 int numberId=0;// Update is called once per framevoid Update(){float data = 0;float[] spectrum = new float[64];//256AudioListener.GetSpectrumData(spectrum, 0, FFTWindow.Hamming);for (int i = 1; i < spectrum.Length - 1; i++){if (data < spectrum[i]){data = spectrum[i];}}Debug.Log("max: " + data);rect[numberId].sizeDelta =new Vector2(10, 100 * data);numberId++;if (numberId >= rect.Length){numberId = 0;}}

在这里插入图片描述
在这里插入图片描述

注意事项

  • 读取音频时,AudioClip不能为空
  • FFTWindow 选择适合的类型

参考

麦克风

http://www.xdnf.cn/news/13298.html

相关文章:

  • git管理github上的repository(二)
  • 中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试
  • 嵌入式学习之系统编程(十三)数据库
  • STL 5 适配器
  • MySQL基础语法总结
  • 如何在 Python 中去除列表重复项并保留顺序
  • BeckHoff <--> 基恩士(CV-X300)三维机械手视觉系统的通讯 控制
  • minio私有桶授权访问
  • Leetcode 3574. Maximize Subarray GCD Score
  • java 面向对象编程
  • Linux下制作Nginx绿色免安装包
  • 7.4.分块查找
  • vue3 字体颜色设置的多种方式
  • sysctl优先级顺序
  • 第3章 MySQL数据类型
  • (八)深度循环神经网络:长序列建模、注意力机制与多模态融合
  • CloudReadering
  • Prompt Tuning、P-Tuning、Prefix Tuning的区别
  • c语言中的hashmap
  • ArkUI-X跨平台Bridge最佳实践
  • 张彬彬《龙骨焚箱》开机 奇幻冒险题材引期待
  • 在微服务架构中,怎么搭建Maven私服
  • crackme007
  • mysql8.4备份与恢复实践
  • bilibili-mcp 使用示例
  • 7.6 Finetuning the LLM on instruction data
  • 论文分享 _ Ladder:一种基于收敛的结构化图区块链_2025-06-10
  • 实战案例-FPGA如何实现JESD204B可重复的延迟
  • 2005-2021年中国地下水位年鉴数据(EXCEL/PDF)包含:各省监测点、监测深度等
  • 【存储系统】