文章目录

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

概要

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

录音,播放

在语言模型中,编码器和解码器都是由一个个的 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.pswp.cn/bicheng/84604.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/84604.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/84604.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

七牛云图片上传 前后端全过程

相关网址&#xff1a;七牛开发者中心 相关网站&#xff1a; 七牛开发者中心 上传流程概述 后端生成上传凭证&#xff1a;服务器端使用七牛云 SDK 生成上传凭证&#xff08;uptoken&#xff09;前端获取凭证&#xff1a;前端通过 API 向后端请求上传凭证前端上传图片&#xff1…

2025年AI生成PPT平台推荐榜单:五大智能工具革新演示创作体验

在数字化办公飞速发展的当下&#xff0c;AI生成PPT平台已成为职场人士、教育工作者和创意人群提升效率的利器。这些平台凭借先进的人工智能技术&#xff0c;打破传统PPT制作的局限&#xff0c;为用户带来便捷、高效且充满创意的制作体验。经过多维度测评&#xff0c;2025年AI生…

PHP框架在内容管理系统开发中的优势:效率、安全与扩展性!

在当今快节奏的Web开发环境中&#xff0c;内容管理系统&#xff08;CMS&#xff09;已成为企业和个人建立动态网站的核心工具。传统的手工编码开发方式在面对复杂业务逻辑、频繁迭代和安全要求时往往力不从心。而PHP框架&#xff08;如Laravel、ThinkPHP、Symfony&#xff09;的…

云原生安全实践:CI/CD流水线集成DAST工具

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 ——从零掌握DevSecOps中的动态安全测试 一、基础概念 1. DevSecOps DevSecOps 是将安全性&#xff08;Security&#xff09;融入开发&#xff08;Dev&am…

【C语言】基础知识框架补充

前文主要介绍了C语言从零开始学习的基本框架与基础知识导览&#xff0c;本文主要补充此前未提及的学习内容&#xff0c;给有意精进C语言者指明一条可供参考的学习路径。 补充一&#xff1a;动态内存管理 核心函数&#xff08;需#include <stdlib.h>&#xff09;&#xf…

垃圾识别检测与分类数据集(猫脸码客第244期)

目标检测与垃圾&#xff1a;技术革新与环境管理的交汇点 在当今社会&#xff0c;城市化进程不断加速&#xff0c;人口持续增长&#xff0c;垃圾处理问题愈发凸显其重要性。有效管理垃圾&#xff0c;不仅关乎环境卫生状况&#xff0c;更直接影响到城市的可持续发展以及居民的生…

【调研报告】2025年与2030年AI及AI智能体 (Agent) 市场份额分析报告

2025年与2030年AI及AI智能体 (Agent) 市场份额分析报告 摘要 本报告旨在深入分析全球人工智能&#xff08;AI&#xff09;市场及其子领域AI智能体的未来发展轨迹&#xff0c;重点关注其在2025年和2030年的市场规模及其占全球GDP和整体AI市场的比例。分析表明&#xff0c;AI市…

台式机电脑CPU天梯图2025年6月份更新:CPU选购指南及推荐

组装电脑选硬件的过程中,CPU的选择无疑是最关键的,因为它是最核心的硬件,关乎着一台电脑的性能好坏。对于小白来说,CPU天梯图方便直接判断两款CPU性能高低,准确的说,是多核性能。下面给大家分享一下台式机电脑CPU天梯图2025年6月版,来看看吧。 桌面CPU性能排行榜2025 台…

小白学Pinia状态管理

目录 1. 什么是 Pinia&#xff1f; 2. 为什么需要 Pinia&#xff1f; 3. Pinia 的三个核心概念 State&#xff08;状态&#xff09;- 存储数据 Getters&#xff08;计算属性&#xff09;- 处理数据 Actions&#xff08;方法&#xff09;- 修改数据 4. 创建一个简单的 St…

Tauri2学习笔记

教程地址&#xff1a;https://www.bilibili.com/video/BV1Ca411N7mF?spm_id_from333.788.player.switch&vd_source707ec8983cc32e6e065d5496a7f79ee6 官方指引&#xff1a;https://tauri.app/zh-cn/start/ 目前Tauri2的教程视频不多&#xff0c;我按照Tauri1的教程来学习&…

SQL进阶之旅 Day 26:分库分表环境中的SQL策略

【SQL进阶之旅 Day 26】分库分表环境中的SQL策略 文章简述 随着业务规模的扩大&#xff0c;单一数据库难以承载海量数据与高并发访问。分库分表成为解决这一问题的关键手段&#xff0c;但同时也带来了 SQL 查询复杂度的显著提升。本文作为“SQL进阶之旅”系列的第26天内容&…

linux之 内存管理(6)-arm64 内核虚拟地址空间变化

一、新内核变动 kernel变化的真快&#xff0c;之前我记得4.x的内核的内核空间的线性映射区位于内核空间的高地址处的128TB&#xff0c;且当前的博客和一些书籍也都还是这样介绍。可翻了翻kernel的Documentation/arm64/memory.rst文档&#xff0c;发现最新的kernel已将这128TB移…

循环神经网络(RNN):从理论到翻译

循环神经网络&#xff08;RNN&#xff09;是一种专为处理序列数据设计的神经网络&#xff0c;如时间序列、自然语言或语音。与传统的全连接神经网络不同&#xff0c;RNN具有"记忆"功能&#xff0c;通过循环传递信息&#xff0c;使其特别适合需要考虑上下文或顺序的任…

window批处理文件(.bat),用来清理git的master分支

echo off chcp 65001 > nul setlocal enabledelayedexpansionecho 正在检查Git仓库... git rev-parse --is-inside-work-tree >nul 2>&1 if %errorlevel% neq 0 (echo 错误&#xff1a;当前目录不是Git仓库&#xff01;pauseexit /b 1 )echo 警告&#xff1a;这将…

C#中的CLR属性、依赖属性与附加属性

CLR属性的主要特征 封装性&#xff1a; 隐藏字段的实现细节 提供对字段的受控访问 访问控制&#xff1a; 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性&#xff1a; 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑&#xff1a; 可以…

【mysql】联合索引和单列索引的区别

区别核心&#xff1a;联合索引可加速多个字段组合查询&#xff0c;单列索引只能加速一个字段。 &#x1f539;联合索引&#xff08;复合索引&#xff09; INDEX(col1, col2, col3)适用范围&#xff1a; WHERE col1 ... ✅ WHERE col1 ... AND col2 ... ✅ WHERE col1 ..…

如何用 HTML 展示计算机代码

原文&#xff1a;如何用 HTML 展示计算机代码 | w3cschool笔记 &#xff08;请勿将文章标记为付费&#xff01;&#xff01;&#xff01;&#xff01;&#xff09; 在编程学习和文档编写过程中&#xff0c;清晰地展示代码是一项关键技能。HTML 作为网页开发的基础语言&#x…

大模型笔记_模型微调

1. 大模型微调的概念 大模型微调&#xff08;Fine-tuning&#xff09;是指在预训练大语言模型&#xff08;如GPT、BERT、LLaMA等&#xff09;的基础上&#xff0c;针对特定任务或领域&#xff0c;使用小量的目标领域数据对模型进行进一步训练&#xff0c;使其更好地适配具体应…

React Native UI 框架与动画系统:打造专业移动应用界面

React Native UI 框架与动画系统&#xff1a;打造专业移动应用界面 关键要点 UI 框架加速开发&#xff1a;NativeBase、React Native Paper、UI Kitten 和 Tailwind-RN 提供预构建组件&#xff0c;帮助开发者快速创建美观、一致的界面。动画提升体验&#xff1a;React Native…

在QT中使用OpenGL

参考资料&#xff1a; 主页 - LearnOpenGL CN https://blog.csdn.net/qq_40120946/category_12566573.html 由于OpenGL的大多数实现都是由显卡厂商编写的&#xff0c;当产生一个bug时通常可以通过升级显卡驱动来解决。 OpenGL中的名词解释 OpenGL 上下文&#xff08;Conte…