iOS - 音频: Core Audio - 播放
环境
iOS 18
Xcode 16.3
swift-driver version: 1.120.5 Apple Swift version 6.1 (swiftlang-6.1.0.110.21 clang-1700.0.13.3)
Target: x86_64-apple-macosx15.0
Core Audio 的架构
声音数据的描述
sample: 一个声道采样的值,采样率定义了每秒从连续信号中提取并组成离散信号的采样个数,它用赫兹(Hz)来表示。
frame: 一个时间常量内的sample的集合
packet: 一个或多个连续的帧
AudioStreamBasicDescription
// CoreAudioBaseTypes.h
// 音频的格式信息
struct AudioStreamBasicDescription
{Float64 mSampleRate; // 采样率AudioFormatID mFormatID; // 采样格式类型AudioFormatFlags mFormatFlags; // 采样格式标志位UInt32 mBytesPerPacket; // 每个packet的字节数// 每个packet的frame数,在未压缩的音频中 mFramesPerPacket == 1 UInt32 mFramesPerPacket;UInt32 mBytesPerFrame; // 每个frame的字节数UInt32 mChannelsPerFrame; // 每个frame的声道数UInt32 mBitsPerChannel; // 每个通道的比特数UInt32 mReserved; // 保留
};
typedef struct AudioStreamBasicDescription AudioStreamBasicDescription;
CF_ENUM(AudioFormatID)
{kAudioFormatLinearPCM = 'lpcm',kAudioFormatAC3 = 'ac-3',kAudioFormat60958AC3 = 'cac3',kAudioFormatAppleIMA4 = 'ima4',kAudioFormatMPEG4AAC = 'aac',kAudioFormatMPEG4CELP = 'celp',kAudioFormatMPEG4HVXC = 'hvxc',kAudioFormatMPEG4TwinVQ = 'twvq',kAudioFormatMACE3 = 'MAC3',kAudioFormatMACE6 = 'MAC6',kAudioFormatULaw = 'ulaw',kAudioFormatALaw = 'alaw',kAudioFormatQDesign = 'QDMC',kAudioFormatQDesign2 = 'QDM2',kAudioFormatQUALCOMM = 'Qclp',kAudioFormatMPEGLayer1 = '.mp1',kAudioFormatMPEGLayer2 = '.mp2',kAudioFormatMPEGLayer3 = '.mp3',kAudioFormatTimeCode = 'time',kAudioFormatMIDIStream = 'midi',kAudioFormatParameterValueStream = 'apvs',kAudioFormatAppleLossless = 'alac',kAudioFormatMPEG4AAC_HE = 'aach',kAudioFormatMPEG4AAC_LD = 'aacl',kAudioFormatMPEG4AAC_ELD = 'aace',kAudioFormatMPEG4AAC_ELD_SBR = 'aacf',kAudioFormatMPEG4AAC_ELD_V2 = 'aacg',kAudioFormatMPEG4AAC_HE_V2 = 'aacp',kAudioFormatMPEG4AAC_Spatial = 'aacs',kAudioFormatMPEGD_USAC = 'usac',kAudioFormatAMR = 'samr',kAudioFormatAMR_WB = 'sawb',kAudioFormatAudible = 'AUDB',kAudioFormatiLBC = 'ilbc',kAudioFormatDVIIntelIMA = 0x6D730011,kAudioFormatMicrosoftGSM = 0x6D730031,kAudioFormatAES3 = 'aes3',kAudioFormatEnhancedAC3 = 'ec-3',kAudioFormatFLAC = 'flac',kAudioFormatOpus = 'opus',kAudioFormatAPAC = 'apac',
};
CF_ENUM(AudioFormatFlags)
{kAudioFormatFlagIsFloat = (1U << 0), // 0x1kAudioFormatFlagIsBigEndian = (1U << 1), // 0x2kAudioFormatFlagIsSignedInteger = (1U << 2), // 0x4kAudioFormatFlagIsPacked = (1U << 3), // 0x8kAudioFormatFlagIsAlignedHigh = (1U << 4), // 0x10kAudioFormatFlagIsNonInterleaved = (1U << 5), // 0x20kAudioFormatFlagIsNonMixable = (1U << 6), // 0x40kAudioFormatFlagsAreAllClear = 0x80000000,kLinearPCMFormatFlagIsFloat = kAudioFormatFlagIsFloat,kLinearPCMFormatFlagIsBigEndian = kAudioFormatFlagIsBigEndian,kLinearPCMFormatFlagIsSignedInteger = kAudioFormatFlagIsSignedInteger,kLinearPCMFormatFlagIsPacked = kAudioFormatFlagIsPacked,kLinearPCMFormatFlagIsAlignedHigh = kAudioFormatFlagIsAlignedHigh,kLinearPCMFormatFlagIsNonInterleaved = kAudioFormatFlagIsNonInterleaved,kLinearPCMFormatFlagIsNonMixable = kAudioFormatFlagIsNonMixable,kLinearPCMFormatFlagsSampleFractionShift = 7,kLinearPCMFormatFlagsSampleFractionMask = (0x3F << kLinearPCMFormatFlagsSampleFractionShift),kLinearPCMFormatFlagsAreAllClear = kAudioFormatFlagsAreAllClear,kAppleLosslessFormatFlag_16BitSourceData = 1,kAppleLosslessFormatFlag_20BitSourceData = 2,kAppleLosslessFormatFlag_24BitSourceData = 3,kAppleLosslessFormatFlag_32BitSourceData = 4
};
About the name: Although this data type has “stream” in its name, you use it in every instance where you need to represent an audio data format in Core Audio—including in non-streamed, standard files. You could think of it as the “audio format basic description” data type. The “stream” in the name refers to the fact that audio formats come into play whenever you need to move (that is, stream) audio data around in hardware or software.
类型中的stream只是表示播放的概念,这里定义的就是iOS音频格式的描述
获取声音的格式信息
public func audioFormat() -> AudioStreamBasicDescription? {var size: UInt32 = 0var audioFile: AudioFileID? // 使用可选类型var status = AudioFileOpenURL(self.path as CFURL, .readPermission, 0, &audioFile)guard status == noErr else {print("*** Error *** filePath: \(self.path) -- code: \(status)")return nil}// 获取音频数据格式var dataFormat = AudioStreamBasicDescription()size = UInt32(MemoryLayout<AudioStreamBasicDescription>.size)status = AudioFileGetProperty(audioFile!,kAudioFilePropertyDataFormat,&size,&dataFormat)// 可选:检查属性获取是否成功guard status == noErr else {print("Failed to get data format: \(status)")AudioFileClose(audioFile!) // 关闭文件防止泄漏return nil}return dataFormat
}
我加载的是一个44.1kHz,双声道的mp3文件
778924083 = 0x2E6D7033 => “.mp3”
AudioStreamPacketDescription
// CoreAudioBaseTypes.h
// 表示每个音频packet的数据
struct AudioStreamPacketDescription {// For example, if the data buffer contains 5 bytes of data, with one byte per packet, then the start offset for the last packet is 4. There are 4 bytes in the buffer before the start of the last packet.// 偏移量// 比如缓冲区有5字节的数据,当每个packet包含1个字节,那最后一个包的这个值就是4SInt64 mStartOffset;UInt32 mVariableFramesInPacket; // frame的个数,如果是格式是CBR按常量编码的,这个值设置为0UInt32 mDataByteSize; // 字节数
};
typedef struct AudioStreamPacketDescription AudioStreamPacketDescription;
Proxy Objects,Properties, Scopes, Elements
名称 | 说明 |
---|---|
Proxy Objects | 音频文件,流的代码抽象 |
Properties | 管理对象的状态或行为 |
Scopes | 作用域:输入/输出 |
Elements | 具体的设备,比如蓝牙,有线… |
Properties的key一般是个常量值,比如 kAudioFilePropertyFileFormat或者kAudioQueueDeviceProperty_NumberChannels.
回调函数: 与Core Audio交互
Core Audio接口通过回调函数与应用交互,一般有下面几种场景
- 音频数据传送到应用程序(例如用于录制;然后通过回调将新数据写入磁盘)
- 从应用程序请求音频数据(例如用于播放;回调从磁盘/内存读取并提供数据)。
- 通知应用程序音频对象已更改状态(回调会执行适当操作,比如更新界面)。
回调函数实现分两步: 注册 && 回调
相关框架
名称 | 说明 |
---|---|
AVFoundation | 提供AVAudioPlayer类,这是一个用于音频播放的简化的原生接口,还提供AVAudioEngine类,用于更复杂的音频处理 |
AudioToolbox | 为Core Audio中的高级服务提供接口,包括Audio Session服务,用于在iOS管理应用程序的音频行为,允许应用程序使用音频插件,包括音频单元和编解码器 |
OpenAL | 提供了与OpenAL配合使用的接口 |
CoreAudioTypes | 提供Core Audio使用的数据类型以及低级服务的接口。 |
示例
播放音乐
使用AudioToolbox.framework
func play() {var format = self.audioFormat()guard format != nil else {return;}// 打开音频文件var status = AudioFileOpenURL(path as CFURL, .readPermission, 0, &audioFile)guard status == noErr else {return}let context = UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque())/**Audio Queue(音频队列)是 iOS 或 Mac OS X 中用来 录音 或 播放音频 的软件对象。它由 AudioQueueRef 数据类型表示,在 AudioQueue.h 中声明音频队列的工作是:* 连接音频硬件* 管理内存* 根据需要,为压缩音频格式使用编解码器* 调解录音或回放*/// 创建输出队列,注册回调函数status = AudioQueueNewOutput(&format!, playbackCallback, context, nil, nil, 0, &queue)guard status == noErr else {print("Create new output queue error")return}status = AudioFileGetProperty(audioFile!, kAudioFilePropertyPacketSizeUpperBound, &size, &maxPacketSize)guard status == noErr else {print("Get maxPacketSize property error")return}// 计算缓冲区大小// For uncompressed audio, the value is 1. For variable bit-rate formats, the value is a larger fixed number, such as 1024 for AAC. For formats with a variable number of frames per packet, such as Ogg Vorbis, set this field to 0.// MP3的值是1152if format!.mFramesPerPacket != 0 {// 每秒的包的数量 = 采样率/每个包的帧数// 比如MP3每秒采样44100次,每个包有1152帧,两者相除就是每秒的包数量let numPacketsPerSecond = format!.mSampleRate / Double(format!.mFramesPerPacket)// 每秒的包的数量 * 包大小的理论峰值, 即1s内占用内存的峰值outBufferSize = UInt32(numPacketsPerSecond * Double(maxPacketSize))} else {outBufferSize = max(maxBufferSize, maxPacketSize)}// 调整缓冲区大小if outBufferSize > maxBufferSize && outBufferSize > maxPacketSize {outBufferSize = maxBufferSize} else if outBufferSize < minBufferSize {outBufferSize = minBufferSize}// 计算包数量并分配包描述数组// 每次读取的包的数量 = 缓冲区大小 / 包大小的理论峰值numPacketsToRead = outBufferSize / maxPacketSizepacketDescs = UnsafeMutablePointer<AudioStreamPacketDescription>.allocate(capacity: Int(numPacketsToRead))packetDescs?.initialize(repeating: AudioStreamPacketDescription(), count: Int(numPacketsToRead))// 分配3个缓冲区for i in 0..<maxBufferNum {var buffer: AudioQueueBufferRef?/**Once allocated, the pointer to the buffer and the buffer's size are fixed and cannot bechanged. The mAudioDataByteSize field in the audio queue buffer structure,AudioQueueBuffer, is initially set to 0.@param inAQ// 分配缓冲区的音频队列The audio queue you want to allocate a buffer.@param inBufferByteSize// 缓冲区大小The desired size of the new buffer, in bytes. An appropriate buffer size depends on theprocessing you will perform on the data as well as on the audio data format.@param outBuffer// 指向新创建的缓冲区On return, points to the newly created audio buffer. The mAudioDataByteSize field in theaudio queue buffer structure, AudioQueueBuffer, is initially set to 0.@result An OSStatus result code.*/AudioQueueAllocateBuffer(queue!, outBufferSize, &buffer)buffers[i] = buffer// 预先读maxBufferNum个缓冲区audioQueueOutput(audioQueue: queue!, queueBuffer: buffer!)}// 启动队列AudioQueueStart(queue!, nil)}
在回调方法中读取音频文件并将数据入队供系统的队列播放
private let playbackCallback: AudioQueueOutputCallback = {inUserData, // UnsafeMutableRawPointer?inAQ, // AudioQueueRefbuffer // AudioQueueBufferRefin// 1. 保护guard let inUserData = inUserData else { return }// 2. 将指针转换为对象实例let player:AudioToolboxTest = Unmanaged<AudioToolboxTest>.fromOpaque(inUserData).takeUnretainedValue()// 3. 实际处理逻辑// 处理音频缓冲区player.audioQueueOutput(audioQueue: inAQ, queueBuffer: buffer)}
public func audioQueueOutput(audioQueue: AudioQueueRef, queueBuffer audioQueueBuffer: AudioQueueBufferRef) {var ioNumBytes = outBufferSizevar ioNumPackets = numPacketsToRead// 读取音频文件let status = AudioFileReadPacketData(audioFile!, // 音频文件false, // 是否缓存// on input the size of outBuffer in bytes.// on output, the number of bytes actually returned.// 输入场景等于缓存大小// 输出场景:比如播放根据文件的实际情况&ioNumBytes, // 包的长度packetDescs, // 音频包信息packetIndex, // 索引值&ioNumPackets, // 包的个数audioQueueBuffer.pointee.mAudioData // 读取到的数据)guard status == noErr else {print("Error reading packet data: \(status)")return}if ioNumPackets > 0 {// 设置音频缓冲区数据大小audioQueueBuffer.pointee.mAudioDataByteSize = ioNumBytes// 将音频数据入队列让系统去播放AudioQueueEnqueueBuffer(audioQueue,audioQueueBuffer,ioNumPackets,packetDescs)// 更新包的索引值self.packetIndex += Int64(ioNumPackets)}}
示例工程
参考
- Apple Core Audio Doc
- AudioFileOpenURL(:::😃
- iOS音频(1)——AudioToolbox
相关文章:
iOS - 音频: Core Audio - 播放
环境 iOS 18 Xcode 16.3 swift-driver version: 1.120.5 Apple Swift version 6.1 (swiftlang-6.1.0.110.21 clang-1700.0.13.3) Target: x86_64-apple-macosx15.0 Core Audio 的架构 声音数据的描述 sample: 一个声道采样的值,采样率定义了每秒从连续信号中提取并组成离散信号…...
Nerfstudio 环境配置与自有数据集(图片和视频)测试全方位全流程实战【2025最新版!!】
一、引言 神经辐射场(Neural Radiance Fields,简称NeRF)是近年来计算机视觉和图形学领域的一项革命性技术,它能够从2D图像中学习复杂的3D场景表示。然而,NeRF技术的实现和应用门槛较高,需要较为专业的计算机视觉和深度学习知识。…...
【Java学习】动态代理有哪些形式?
Java动态代理的两种主要形式 动态代理在Java中有两种主要的实现方式,它们各有特点和使用场景: 1. JDK动态代理 (基于接口) 特点: Java标准库自带的功能(java.lang.reflect.Proxy)只能代理接口,不能代理…...
Android Studio 中实现方法和参数显示一行
Android Studio 中实现方法和参数显示一行,可通过以下步骤配置: 一、基础格式化设置 快捷键格式化 选中代码后使用 Ctrl Alt L(Windows/Linux)或 Cmd Option L(Mac)进行快速格式化27。 菜单操作…...
SQLyog中DELIMITER执行存储过程时出现的前置缩进问题
在SQLyog中执行存储过程时出现的前置缩进问题,实际上反映了SQLyog对SQL语句解析的一个特殊行为。以下是详细解释和解决方案: 问题根源 SQLyog的语句分隔逻辑: SQLyog默认会根据分号(;)和换行自动分隔SQL语句 当代码有缩进时,SQLy…...
基于Spring Boot 3.0、ShardingSphere、PostgreSQL或达梦数据库的分库分表
要实现基于Spring Boot 3.0、ShardingSphere、PostgreSQL或达梦数据库的分库分表,首先需要对ShardingSphere进行一些基本配置。你提到的溯源码、批次号等数据需要考虑到跨年数据的存储,因此要设计一个能够动态扩展的分表策略 添加ShardingSphere依赖 在…...
vscode chrome调试怎么在所有浏览器都好使
chrome调试时只能在打开的浏览器里进行调试,其它打开的chrome浏览器就不能调试了,怎么解决。 右键点击 Chrome 的快捷方式图标,选择属性 在目标一栏,最后加上--remote-debugging-port9222 注意要用空格隔开 lanch.json 文件配置 …...
20250429在Ubuntu 20.04.6下安装VMware Workstation16
20250429在Ubuntu 20.04.6下安装VMware Workstation16 2025/4/29 20:16 缘起:1、在ubuntu14.04下git clone异常该如何处理呢? 2、请问 现在 编译NanoPi NEO的FriendlyCore系统使用ubuntu哪一个版本比较好? ubuntu14.04 编译异常/下载不了&am…...
Java高频面试之并发编程-10
hello啊,各位观众姥爷们!!!本baby今天来报道了!哈哈哈哈哈嗝🐶 面试官:ThreadLocalMap 怎么解决 Hash 冲突的? ThreadLocalMap 是 ThreadLocal 的核心实现,它采用 开放…...
【Tauri2】035——sql和sqlx
前言 这篇就来看看插件sql SQL | Taurihttps://tauri.app/plugin/sql/ 正文 准备 添加依赖 tauri-plugin-sql {version "2.2.0",features ["sqlite"]} features可以是mysql、sqlite、postsql 进去features看看 sqlite ["sqlx/sqlite&quo…...
C++/SDL 进阶游戏开发 —— 双人塔防(代号:村庄保卫战 16)
🎁个人主页:工藤新一 🔍系列专栏:C面向对象(类和对象篇) 🌟心中的天空之城,终会照亮我前方的路 🎉欢迎大家点赞👍评论📝收藏⭐文章 文章目录 […...
VScode与远端服务器SSH链接
这里写自定义目录标题 简介步骤 简介 这里是使用密钥文件链接 步骤 首先在windows CMD中运行 ssh-keygen -t rsa,生成本机的公钥和私钥 这里id rsa.pub就是公钥,在服务器端使用,id rsa是私钥在用户端使用;通常目录在C:/Users/Your name/…...
数据结构入门:详解顺序表的实现与操作
目录 1.线性表 2.顺序表 2.1概念与结构 2.2分类 2.2.1静态顺序表 2.2.2动态顺序表 3.动态顺序表的实现 3.1.SeqList.h 3.2.SeqList.c 3.2.1初始化 3.2.2销毁 3.2.3打印 3.2.4顺序表扩容 3.2.5尾部插入及尾部删除 3.2.6头部插入及头部删除 3.2.7特定位置插入…...
Reactor框架介绍
Reactor(反应器模式)是一种事件驱动的设计模式,广泛用于高性能网络编程和异步I/O处理。它的核心思想是将事件分发与业务逻辑解耦,通过统一的机制处理多路I/O事件。 这个在android蓝牙中大量使用,如果这里不懂,那么很难看懂底层的逻辑,所以我们在这片文章中做一个介绍 …...
Nacos 3.0 正式发布:MCP Registry、安全零信任、链接更多生态
Nacos 3.0 正式版本发布啦!升级 MCP Registry,围绕着 MCP 服务管理,MCP 多种类型注册,包含 MCP Server 注册、编排、动态调试和管理,并且提供 Nacos-MCP-Router 可以进行 MCP 动态发现,可以自动安装、代理 …...
前端安全中的XSS(跨站脚本攻击)
XSS 类型 存储型 XSS 特征:恶意脚本存储在服务器(如数据库),用户访问受感染页面时触发。场景:用户评论、论坛帖子等持久化内容。影响范围:所有访问该页面的用户。 反射型 XSS 特征:恶意脚本通过…...
go单向链表
需求 实现单向链表的节点顺序添加、顺序遍历。 实现 package mainimport ("fmt" )type zodiac_sign struct {number intdizhi stringanimal stringyear intnext *zodiac_sign }// 添加 // func add_node_by_order(previous_node zodiac_sign, current_node z…...
Python小程序:上班该做点摸鱼的事情
系统提醒 上班会忘记一些自己的事,所以你需要在上班的的时候突然给你弹窗,你就知道要做啥了 源码 # -*- coding:utf-8 -*- """ 作者:杨桃清 日期: 2025年04日29 21:51:24 """ import datetime import time import thre…...
uni-app中使用RenderJs 使用原生js
RenderJs运行的层叫【视图层】,Uniapp原生Script叫【逻辑层】,逻辑层要调用视图层需要使用一个叫【watcher】,具体怎么调用呢 为了实现这两层之间的通信,uniapp提供了一些特定的机制。以下是对这些通信机制的详细解释,…...
51c自动驾驶~合集37
我自己的原文哦~ https://blog.51cto.com/whaosoft/13878933 #DETR->DETR3D->Sparse4D 走向长时序稀疏3D目标检测 一、DETR 图1 DETR架构 DETR是第一篇将Transformer应用到目标检测方向的算法。DETR是一个经典的Encoder-Decoder结构的算法,它的骨干网…...
uniapp 小程序 安卓苹果 短视频解决方案
需求 要做类似抖音小程序的功能 思路 uniapp 使用swiper滑块 实现滑动 使用video播放视频 遇到的问题 1 video组件在小程序可以使用 uni.createVideoContext api控制 2 但是在app端会有层级问题(因为使用的原生组件具体看官方文档)导致无法正常滑动…...
LeetCode58_最后一个单词的长度
LeetCode58_最后一个单词的长度 标签:#字符串Ⅰ. 题目Ⅱ. 示例 0. 个人方法 标签:#字符串 Ⅰ. 题目 给你一个字符串 s,由若干单词组成,单词前后用一些空格字符隔开。返回字符串中 最后一个 单词的长度。 单词 是指仅由字母组成、…...
深入理解Spring AI框架的核心概念
深入理解Spring AI框架的核心概念 前言 在当今人工智能飞速发展的时代,将AI技术集成到应用程序中已成为众多开发者关注的焦点。Spring AI框架为Java开发者提供了便捷的途径来实现这一目标。理解其核心概念对于充分发挥框架的潜力至关重要。本文将详细探讨Spring A…...
技术驱动与模式创新:开源AI大模型与S2B2C商城重构零售生态
摘要:在移动互联网与人工智能技术深度融合的背景下,零售行业正经历从“人找货”到“货找人”的范式转移。本文以开源AI大模型、AI智能名片、S2B2C商城小程序源码为核心技术要素,结合无人便利店、盒马鲜生、王府井二次元业态等商业实践&#x…...
精益数据分析(30/126):电商商业模式的深度剖析与关键指标解读
精益数据分析(30/126):电商商业模式的深度剖析与关键指标解读 在创业与数据分析的漫漫征途中,我们都在不断探寻如何更好地理解和运用商业数据,以实现业务的蓬勃发展。今天,我依旧带着和大家共同进步的初心…...
玩玩OCR
一、Tesseract: 1.下载windows版: tesseract 2. 安装并记下路径,等会要填 3.保存.py文件 import pytesseract from PIL import Image def ocr_local_image(image_path):try:pytesseract.pytesseract.tesseract_cmd rD:\Programs\Tesseract-OCR\tesse…...
gradle 下载的tencent的镜像
distributionUrlhttps://mirrors.cloud.tencent.com/gradle/gradle-5.4.1-all.zip distributionUrlhttps://mirrors.aliyun.com/gradle/distributions/v5.4.1/gradle-5.4.1-all.zip 参考: gradle 镜像地址,解决 AS 下载缓慢或者下不下来的问题-CSDN博客...
【含文档+PPT+源码】基于微信小程序的乡村振兴民宿管理系统
项目介绍 本课程演示的是一款基于微信小程序的乡村振兴民宿管理系统,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Java 学习者。 1.包含:项目源码、项目文档、数据库脚本、软件工具等所有资料 2.带你从零开始部署运行本套系统 3.该…...
【Redis——数据类型和内部编码和Redis使用单线程模型的分析】
文章目录 Redis的数据类型和内部编码单线程模型的工作过程Redis虽然是一个单线程模型,为啥效率那么高,速度快呢? 总而言之,Redis提供的哈希表容器并不一定真的是真的哈希表,而是在特点的场景下,用别的容器去…...
leetcode day37 474
474 一和零 给你一个二进制字符串数组 strs 和两个整数 m 和 n 。 请你找出并返回 strs 的最大子集的长度,该子集中 最多 有 m 个 0 和 n 个 1 。 如果 x 的所有元素也是 y 的元素,集合 x 是集合 y 的 子集 。 示例 1: 输入:s…...
【计算机视觉】目标检测:深度解析YOLOv9:下一代实时目标检测架构的创新与实战
深度解析YOLOv9:下一代实时目标检测架构的创新与实战 架构演进与技术创新YOLOv9的设计哲学核心创新解析1. 可编程梯度信息(PGI)2. 广义高效层聚合网络(GELAN)3. 轻量级设计 环境配置与快速开始硬件需求建议详细安装步骤…...
Android Studio Profiler
1.我们想要查看自己方法的调用链,或者分析方法耗时的情况,可以选择Android Studio的Profiler,比较方便快捷。如下: 2.基本的面板参数讲解: 3.可以通过搜索,查看对应的方法,以及方法的调用链…...
Android Studio for Platform(ASFP)真机调试
连接设备 由于ubuntu连接adb设备每次都需要配置usb权限,很麻烦。并且每次换设备还要重新配置,我多数设备都是用wifi的adb方式连接。 开发板显示 连接显示器配合usb鼠标或者遥控器操作(因为开发板默认开启了adb,我这里是使用有线…...
如何个人HA服务器地址和长期密钥
下面分两步说明如何获取你的 Home Assistant 服务器地址以及创建“长期访问令牌”(Long-Lived Access Token),并给出一个简单的 Python 调用示例。 一、获取 Home Assistant 服务器地址 默认域名/端口 如果你在本机或局域网内安装并使用默认设…...
生物化学笔记:神经生物学概论04 视觉通路简介视网膜视网膜神经细胞大小神经节细胞(视错觉)
视觉通路简介 神经节细胞的胞体构成一明确的解剖层次,其外邻神经纤维层,内接内丛状层,该层在鼻侧厚约10~20μm,最厚在黄斑区约60~80μm。 全部细胞数约为120万个(1000000左右)。 每个细胞有一轴突ÿ…...
C++——调用OpenCV和NVIDIA Video Codec SDK库实现使用GPU硬解码MP4视频文件
系列文章目录 参考博客 参考博客 参考博客 文章目录 系列文章目录前言一、下载安装NVIDIA Video Codec SDK1、下载NVIDIA Video Codec SDK2、安装NVIDIA Video Codec SDK 二、下载编译安装OpenCV1、下载OpenCV2、编译安装OpenCV3、配置环境变量4、报错解决报错一: …...
dify升级最新版本(保留已创建内容)
dify安装参考文章: DeepSeek+Dify本地部署私有化知识库 如果之前安装的时候,是通过docker镜像的方式。 从网上下载最新的dify包,下载地址: https://github.com/langgenius/dify 下载完成后,把文件覆盖原…...
4、RabbitMQ的七种工作模式介绍
目录 一、Simple(简单模式) 1.1 概念 1.2 代码实现 消费者 运行结果 二、Work Queue(工作队列) 2.1 概念 1.2 代码实现 生产者 消费者 运行结果 三、Publish/Subscribe(发布/订阅模式) 3.1 概念 3.2 代码实现 生产者…...
React Three Fiber 详解:现代 Web3D 的利器
React Three Fiber 详解:现代 Web3D 的利器 随着 Web 技术的发展,3D 场景与交互已经不再是游戏开发者的专利。越来越多的网站、产品页、交互动画,开始大量引入 3D 元素。要在 React 项目中高效使用 WebGL,React Three Fiber(简称 R3F)成为了目前最主流的选择。 今天这篇…...
同步与互斥(同步)
线程同步 条件变量 当⼀个线程互斥地访问某个变量时,它可能发现在其它线程改变状态之前,它什么也做不了。 例如⼀个线程访问队列时,发现队列为空,它只能等待,只到其它线程将⼀个节点添加到队列中。这种情况就需要⽤到条…...
C语言教程(二十一):C 语言预处理器详解
一、预处理器概述 C语言预处理器是一个文本替换工具,它会对源代码进行扫描,处理以 # 开头的预处理指令。这些指令可以控制预处理器的行为,实现宏定义、文件包含、条件编译等功能。预处理器的主要作用是为后续的编译过程准备代码。 二、常见的…...
grafana/loki 设置日志保留时间
loki:limits_config:retention_period: 189h参考官网 Configuring the retention period...
Spring Boot × K8s 监控实战-集成 Prometheus 与 Grafana
在微服务架构中,应用的可观测性至关重要。Kubernetes 已成为容器化部署的标准,但其自身的监控能力有限,需要与其他工具集成才能实现详细的运行数据采集与分析。 本文将通过 Spring Boot Kubernetes Prometheus Grafana 实战,打…...
SpringBoot+Mybatis通过自定义注解实现字段加密存储
😊 作者: 一恍过去 💖 主页: https://blog.csdn.net/zhuocailing3390 🎊 社区: Java技术栈交流 🎉 主题: SpringBootMybatis实现字段加密 ⏱️ 创作时间: 2025年04月…...
Vue3调度器错误解析,完美解决Unhandled error during execution of scheduler flush.
目录 Vue3调度器错误解析,完美解决Unhandled error during execution of scheduler flush. 一、问题现象与本质 二、七大高频错误场景与解决方案 1、Setup初始化陷阱 2、模板中的"幽灵属性" 3、异步操作的"定时炸弹" 4、组件嵌套黑洞 5…...
第35周Zookkeeper+Dubbo Zookkeeper
第35周ZooKeeperDubbo ZooKeeper 一、周介绍 本周主要内容包括ZooKeeper、Dubbo以及面试三部分。 1.1 ZooKeeper 节点介绍 ZooKeeper的数据结构核心是每个node节点。节点具有属性、特点和功能,其数据结构为树形结构,类似于多叉树,分隔符是…...
基于tabula对pdf中多个excel进行识别并转换成word中的优化(四)
对上一节进行优化: 1、识别多个excel 2、将表格中的nan替换成空字符串 一、示例中的pdf内容 二、完整代码参考: import tabula import numpy as np from docx import Document from docx.oxml.ns import qn from docx.oxml import OxmlElementdef get_t…...
Electron-vite中ELECTRON_RENDERER_URL环境变量如何被设置的
近期我专注于前端技术栈 Electron 与 Vue3 的学习实践,依照教程网站 快速开始 | electron-vite 的快速入门指引,搭建了一个示例项目。成功完成项目下载,并通过 npm run dev 命令启动项目后,在研读项目 main 目录下的 index.ts 文件…...
Electron Forge【实战】桌面应用 —— 将项目配置保存到本地
最终效果 定义默认配置 src/initData.ts export const DEFAULT_CONFIG: AppConfig {language: "zh",fontSize: 14,providerConfigs: {}, };src/types.ts export interface AppConfig {language: zh | enfontSize: numberproviderConfigs: Record<string, Recor…...
gem5-gpu 安装过程碰到的问题记录 关于使用 Ruby + Garnet
如何使用Garnet? 这并不像一组命令行参数那么简单。要使用gem5-gpu+garnet,您可能需要修改python配置脚本。 问题是配置文件gem5-gpu/configs/gpu_protocol/VI_hammer_fusion.py指定了链接的intBW和extBW。 看来Garnet不支持这一点。然而,似乎所有的链路都是相同的带宽,所…...