如何转换音频以便可以跨设备传输

2024-02-29

我已经寻找这个问题的答案大约一个月了,所以非常感谢您的帮助!

我正在使用 AVAudioEngine 来录制音频。该音频是使用水龙头录制的:

localInput?.installTap(onBus: 0, bufferSize: 4096, format: localInputFormat) {

它被记录为AVAudioPCMBuffer类型。需要转换为类型[UInt8]

我用这个方法这样做:

func audioBufferToBytes(audioBuffer: AVAudioPCMBuffer) -> [UInt8] {
    let srcLeft = audioBuffer.floatChannelData![0]
    let bytesPerFrame = audioBuffer.format.streamDescription.pointee.mBytesPerFrame
    let numBytes = Int(bytesPerFrame * audioBuffer.frameLength)
    
    // initialize bytes by 0 
    var audioByteArray = [UInt8](repeating: 0, count: numBytes)
    
    srcLeft.withMemoryRebound(to: UInt8.self, capacity: numBytes) { srcByteData in
        audioByteArray.withUnsafeMutableBufferPointer {
            $0.baseAddress!.initialize(from: srcByteData, count: numBytes)
        }
    }
    
    return audioByteArray
}

然后音频被写入输出流。在另一台设备上,数据需要转换回 AVAudioPCMBuffer 才能播放。我用这个方法:

func bytesToAudioBuffer(_ buf: [UInt8]) -> AVAudioPCMBuffer {
    
    let fmt = AVAudioFormat(commonFormat: .pcmFormatFloat32, sampleRate: 44100, channels: 1, interleaved: true)
    let frameLength = UInt32(buf.count) / fmt.streamDescription.pointee.mBytesPerFrame
    
    let audioBuffer = AVAudioPCMBuffer(pcmFormat: fmt, frameCapacity: frameLength)
    audioBuffer.frameLength = frameLength
    
    let dstLeft = audioBuffer.floatChannelData![0]
    
    buf.withUnsafeBufferPointer {
        let src = UnsafeRawPointer($0.baseAddress!).bindMemory(to: Float.self, capacity: Int(frameLength))
        dstLeft.initialize(from: src, count: Int(frameLength))
    }
    
    return audioBuffer
}

但是,我的逻辑一定有问题,因为在设备上,当我播放音频时,我确实听到了一些声音,但听起来像是静态的。

正如我所说,任何帮助都是值得赞赏的,我已经在这个问题上停留了一段时间了。


EDIT

感谢你目前的帮助。我已改用数据。所以我的转换看起来像这样(我在网上找到了这段代码):

func audioBufferToData(audioBuffer: AVAudioPCMBuffer) -> Data {
    let channelCount = 1
    let bufferLength = (audioBuffer.frameCapacity * audioBuffer.format.streamDescription.pointee.mBytesPerFrame)
    
    let channels = UnsafeBufferPointer(start: audioBuffer.floatChannelData, count: channelCount)
    let data = Data(bytes: channels[0], count: Int(bufferLength))

    return data
}

转换回 AVAudioPCMBuffer 如下所示:

func dataToAudioBuffer(data: Data) -> AVAudioPCMBuffer {
    let audioFormat = AVAudioFormat(commonFormat: .pcmFormatFloat32, sampleRate: 8000, channels: 1, interleaved: false)
    let audioBuffer = AVAudioPCMBuffer(pcmFormat: audioFormat, frameCapacity: UInt32(data.count)/2)
    audioBuffer.frameLength = audioBuffer.frameCapacity
    for i in 0..<data.count/2 {
        audioBuffer.floatChannelData?.pointee[i] = Float(Int16(data[i*2+1]) << 8 | Int16(data[i*2]))/Float(INT16_MAX)
    }
    
    return audioBuffer
}

不幸的是,同样的问题仍然存在......


EDIT 2

我创建了一个项目来模拟这个问题。它所做的就是录制音频,将其转换为数据,再将其转换回 AVAudioPCMBuffer,然后播放音频。

链接在这里:https://github.com/Lkember/IntercomTest https://github.com/Lkember/IntercomTest


EDIT 3

使用具有 2 个通道的设备时发生崩溃,但我已修复它。


EDIT 4

提交的答案解决了我的示例项目中的问题,但它没有解决我的主项目中的问题。我在这里添加了一个新问题:

如何通过 OutputStream 发送 NSData https://stackoverflow.com/questions/42936113/how-to-send-nsdata-over-an-outputstream


免责声明:好的,这完全基于苹果文档的理论 - 我以前没有这样做过,你的代码也没有提供足够的信息,无法理解你想要完成的整个事情。

首先,您正在尝试将.floatChannelData to Uint8根据文档集,其中

通过将给定浮点值舍入为零来创建新实例。

这将导致一个数组充满probably错误或更糟糕的是,空值(空,如零)。

以我的理解,.withMemoryRebound will NOT让您以整数形式访问浮点数。隐式转换will削减数字,因此会扭曲你的结果。这不是你想要的。

相反,你应该使用音频转换器服务(文档) https://developer.apple.com/reference/audiotoolbox/audio_converter_services?language=objc

转换浮点audioBuffersecurely并且无损于整数audioBuffer。

我认为这应该为您指明正确的方向。 您还应该检查您的格式AVAudioPCMBuffer在开始转换之前。处理可能取决于具体情况。

我希望我能帮忙。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何转换音频以便可以跨设备传输 的相关文章

  • Admob 广告无法快速显示

    您好 我正在尝试将 admob 广告添加到已使用 swift 上传到应用商店的应用程序中 我在 admob 中制作了一个应用程序并复制了 appid 和广告 id 并显示了各自的横幅广告和插页式广告 这里的问题是当我写这行时 request
  • 无法从 iOS 中的框架访问 .nib(XIB) 文件

    我已经从现有的代码库中创建了一个框架 并尝试在新的代码库中使用它 这很好用 但是当我尝试访问属于我的框架包的一部分的 nib 文件时 我的应用程序崩溃了 这是我用来访问视图控制器 XIB 文件的代码 testViewController c
  • NSString stringWithContentsOfFile 失败,错误代码似乎错误

    我正在尝试将文件加载到字符串中 这是我正在使用的代码 NSError error nil NSString fullPath NSBundle mainBundle pathForResource filename ofType html
  • 无法连接到 iTunes Store(获取应用内购买列表)

    我正在尝试从我的应用程序的应用程序内购买项目商店中获取列表 这是我所做的 安装了新的配置文件并启用了应用内购买 替换配置文件很棘手 但我认为我的设置是正确的 验证税务和银行信息是否正常 该应用程序已在商店出售 创建测试用户 在测试设备上以测
  • .showsPhysics 内存泄漏

    我最近花了 5 个小时尝试调试 Spritekit 应用程序中的内存泄漏 应用程序启动后 我注意到内存使用量略有上升 我花了 5 个小时中的 3 个小时挖掘参考资料 了解强与弱的关系ARC https developer apple com
  • 如何在iOS中处理1到3个手指的滑动手势

    我使用以下代码来处理代码中的 1 根手指滑动 UISwipeGestureRecognizer swipe UISwipeGestureRecognizer alloc initWithTarget self action selector
  • Swift SpriteKit edgeLoopF​​romRect 问题

    下面的代码可以识别底部和顶部边缘场景和球按预期弹开 但是 那左边缘和右边缘现场的情况一直被破坏 如果施加足够的力 球会离开屏幕 然后最终返回 就好像场景的边缘超出了 iPhone 模拟器窗口的边缘 import SpriteKit clas
  • AppStore 提交:错误 ITMS-9000:“无效的捆绑结构 - 不允许二进制文件‘MyApp.app/BuildAgent’

    我陷入了以下错误 我根本不明白 错误 ITMS 9000 无效的捆绑结构 不允许使用二进制文件 MyApp app BuildAgent 您的应用程序可能只包含一个可执行文件 当我使用 Xcode 从 Archive 导出到 IPA 时 我
  • locationOfTouch 和 numberOfTouches

    你好 我有这个识别器 设置为 2 次触摸 但它只返回一个 而不是两个 CGPoint void gestureLoad UIGestureRecognizer recognizer recognizer UITapGestureRecogn
  • 如何制作带有 SWIFT 图像的弹出窗口

    我想知道如何制作类似于此示例的弹出窗口 原始窗口充满了按钮 选择这些按钮后将拉出我想要使用的图像 我会简单地创建一个可重用的UIView组件以及作为子视图所需的一切 例如UIImageView为了你的形象 UILabel or a UIBu
  • 每 24 小时触发一次方法

    我正在尝试每天在给定时间触发一个方法 我尝试了一些方法 但我无法真正使其发挥作用 任何意见 将不胜感激 此外 如果无论应用程序是否打开它都会触发 那就更理想了 这可能吗 UI本地通知 http developer apple com lib
  • iOS 中 NSDecimalNumber 的小数分隔符错误

    我尝试通过以下方式输出具有正确的小数分隔符的十进制数的描述 NSString strValue 9 94300 NSDecimalNumber decimalNumber NSDecimalNumber decimalNumberWithS
  • 从按钮执行 Segue 时应用程序冻结

    我的故事板中有一个按钮 它呈现一个带有模式序列的视图控制器 每次按下此按钮时 应用程序都会冻结 没有崩溃 也没有错误消息 prepareForSegue被调用 所有应该存在的视图控制器都在代码中prepareForSegue 但它们不会出现
  • 从命令行添加 Xcode 开发者帐户

    我正在尝试使用xcodebuild allowProvisioningUpdates在我只能通过命令行访问的计算机 Azure Devops macOS 托管计算机 上 不幸的是 根据man xcodebuild为了使用 allowProv
  • ReactiveCocoa 将 SignalProducers 合二为一

    我正在使用 ReactiveCocoa 并且我有几个 SignalProducers let center NSNotificationCenter defaultCenter let signalProducer1 center rac
  • “预期的 ';'在 Swift 下的顶级声明符之后”

    我正在尝试将所有颜色设置在一个 Swift 文件中 该文件可以在我的整个应用程序中使用 下面的代码会导致 import Foundation import UIKit class DotColors let tsblueColor UICo
  • TableViewController 的 viewDidLoad 未触发

    我一直在关注这个tutorial http www appcoda com ios programming sidebar navigation menu 有一个滑出式菜单 我添加了一个 TableViewController 它将显示文章
  • Objective-C 中发送给对象的消息可以被监听或者打印出来吗? [复制]

    这个问题在这里已经有答案了 可能的重复 Objective C 中拦截方法调用 https stackoverflow com questions 1618474 intercept method call in objective c 如
  • 如何解决 Xcode 5 中的红色(已移动)文件?

    在 Xcode 4 中 当您要移动文件时 可以通过单击右侧菜单中的按钮并通过 Finder 选择新位置来解析文件的新位置 在 Xcode 5 中 右侧菜单中没有按钮 我还没有找到任何方法通过右键单击文件或顶部菜单栏选项来指定文件的新位置 在
  • 像 TraceGL 一样分析 Objective C 中的代码路径?

    TraceGL 是一个非常简洁的项目 它允许 JS 程序员跟踪 Javascript 中的代码路径 它看起来像这样 我想为 Objective C 构建类似的东西 我知道运行时使跟踪方法调用变得相当容易 但是我如何跟踪控制流 例如 在上面的

随机推荐

  • 安装蓝图时,环境上下文中不允许初始化程序错误

    我正在尝试使用 blueprintjs core我的项目中的库 但是 当我编译代码时 我收到许多这样的错误 node modules blueprintjs core dist common classes d ts 4 30 error
  • C# 中的 XML 多行注释 - 我做错了什么?

    根据本文 http blogs msdn com ansonh archive 2006 09 11 750056 aspx 可以获得多行 XML 注释 而不是使用 use 这是我对多行注释是什么以及我希望发生的情况的解释
  • Visual Studio 2005 清洁解决方案[重复]

    这个问题在这里已经有答案了 如果我有一个包含 10 个项目的解决方案 当我单击 清理解决方案 时 是否只是清理主启动项目解决方案中的 bin debug 或每个项目目录中的 bin debug 它针对当前选定的配置 例如调试 发布等 清理解
  • 在 ng2-select2 中使用 AJAX

    我的 angular2js 项目中有很多下拉菜单 我在用ng2 选择2 https github com NejcZdovc ng2 select2对于这些下拉菜单 在某些下拉列表中 我需要根据用户在 select2 搜索框中输入的字符串来
  • OpenAPI 规范 (YML/YAML):所有 $refs 替换或扩展为其定义(带有模式验证)

    我正在寻找一些解决方案或者一些脚本 可以帮助我通过模式验证替换 ref 或扩展其在 YML 文件中的定义 具体请看下面的例子 示例 使用 ref 输入 pets petId get summary Info for a specific p
  • 识别UIWebview的提交按钮点击

    我有一个带有多个按钮的 UIWebView 页面 需要识别点击的是哪个按钮UIWebView UIWebview加载内容的页面源码
  • 如何获取图片资源

    我应该如何获取imageButton的当前图像资源 我需要这样的东西 imageButton getImageResource 多谢 我认为你不能 当前的 API 不允许这样做 但如果你真的需要这个 你可以这样做 imageButton s
  • 为锦标赛系统分配奖品

    我正在寻找一种将数字分布到 x 个单位的方法 我什至不知道如何表达这个词 所以我举个例子 有一场锦标赛 总奖金为 1000 美元 我希望前 20 名获胜者 参赛者能够从中赢得一些东西 我需要一个数学算法 公式 将其分配给这些玩家 并让我有能
  • 在 Spring Boot 的 application.properties 中使用 env 变量

    我们正在开发一个Spring Boot Web应用程序 我们使用的数据库是MySQL 我们的设置是我们首先测试它locally 意味着我们需要在我们的PC上安装MySQL 然后我们推送到 Bitbucket Jenkins 自动检测到 Bi
  • 如何使 str.splitlines 方法不按十六进制字符分割行?

    我正在尝试使用 str splitlines 解析 GNU Strings 实用程序的输出 这是 GNU Strings 的原始输出 279304 9k pN n 279340 9k PN n 279376 9k
  • Go 语言的 Setter

    抱歉问这个基本问题 我是 Go 语言的新手 我有一个名为的自定义类型ProtectedCustomType我不希望其中的变量是set直接由调用者调用 而想要一个Getter Setter方法来做到这一点 下面是我的ProtectedCust
  • 获得正确的方法来设计复选框,而无需跟随标签标签

    我使用一些 CSS 来重新设计 ASP NET 中的复选框 input type checkbox display none important cursor pointer input type checkbox not disabled
  • 单元测试 REST API

    我在单元测试和模拟方面有一些经验 在我有限的经验中 我会使用这两者来测试服务层 例如 模拟 存根 数据库以消除依赖性并集中于对业务逻辑进行单元测试 现在 我正在创建一个将使用 RESTful Web 服务的包装 API 实现 发回给我的js
  • 如何在 Google Play 中切换语言? [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我正在对 Google Play 进
  • 为什么在单元测试中在$compile(element)(scope)之后调用scope.$digest()

    以下是用于测试指令的非常常见的通用场景 var element scope beforeEach inject function rootScope compile scope rootScope new element angular e
  • Javascript 舍入 v C# 舍入

    我在 ASP NET MVC 中有一个发票页面 我正在计算商品及服务税 在 javascript 中 这是结果 165 45 0 1 16 544999999999998 在 C 中我得到 165 45 0 1 16 545 这些轮次不同
  • 比较两个日期Google Apps脚本

    最好的方法是什么比较两个日期 var int e parameter intlistbox var startDate rSheet getRange parseInt int 1 1 getValues returns Sat Jun 3
  • 如何在浏览器中配置 webpack -libraryTarget + splitChunks + require

    我正在用 JS 为网页编写库 并通过 Webpack 编译 它 我需要在单独的 Webpack 项目中的页面上导入 需要 如 requirejs 这些库 库可以托管在两个单独的路径上 一个是相对路径 第二个是绝对路径 我如何配置 webpa
  • 未找到与模式匹配的测试程序集 - Visual Studio 测试 - VSTS

    这个问题类似于 VSTS 测试组件 未找到测试组件 https stackoverflow com questions 47288399 vsts test assemblies no test assemblies found 当时似乎已
  • 如何转换音频以便可以跨设备传输

    我已经寻找这个问题的答案大约一个月了 所以非常感谢您的帮助 我正在使用 AVAudioEngine 来录制音频 该音频是使用水龙头录制的 localInput installTap onBus 0 bufferSize 4096 forma