最近在做UAC的项目大概就是接收内核UAC的事件也就是声音相关事件。然后就是pcm_read和AudioTrackr-write之间互传。感觉略微有点奇怪所以简单总结一下。1 UAC的简要流程open_netlink_socket 打开内核窗口类似于ioctl。recvfrom 接收数据。UAC_CAP_START 处理开始播放事件。host_to_devicetracker_data_thread 播放线程。pcm_read-(AudioTrackr-write)pcm_openpcm_readpcm_closeUAC_CAP_STOP 处理停止播放事件。UAC_PLAY_START 处理开始录音事件。device_to_hostrecorder_data_thread(AudioRecord-read)-pcm_writepcm_openpcm_writepcm_closeUAC_PLAY_STOP 处理停止录音事件。2 安卓音频系统https://source.android.com/docs/core/audio?hlzh-cn关于UAC的内容居然也有说https://source.android.com/docs/core/audio/usb?hlzh-cn不过下面这两个图我觉得直观一丢丢。还看到下面这个都包浆了的图。。。大致就是几层1 Java App层这一层封装最完善但是只有最常规的操作给开发app的帅哥做傻瓜式操作的。使用android.media.MediaPlayer。2 Framework层这一层可以使用AudioTracker和AudioRecorder这一层接口比较底层一点提供的功能比较多。可以实现实时处理和一些特效。Java和C都可以用。下面还有个AudioFlinger是用来做混音的。也是上下层的分隔。所以绕过Framework层直接用HAL的接口可能就有问题。3 HAL接口。有HIDL和AIDL的这一层理论上可以用但是貌似比较少起码我们公司的大神都不在这层搞事。4 ALSA接口这一层是标准Linux的花样也是非常多。3 App接口没啥好说的这部分我也不是太熟悉直接怼media.MediaPlayer即可。代码说明一切吧。package com.example.audioplayer; import android.media.MediaPlayer; import android.os.Bundle; import android.view.View; import android.widget.Button; import androidx.appcompat.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { private MediaPlayer mediaPlayer; Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button playButton findViewById(R.id.play_button); Button stopButton findViewById(R.id.stop_button); // 播放本地音频文件 mediaPlayer MediaPlayer.create(this, R.raw.example_audio); // 如果你想播放网络音频流可以使用下面的代码 // mediaPlayer new MediaPlayer(); // try { // mediaPlayer.setDataSource(http://your-audio-url.com/audio.mp3); // mediaPlayer.prepare(); // 同步准备可能会阻塞主线程建议使用异步准备 // } catch (IOException e) { // e.printStackTrace(); // } playButton.setOnClickListener(new View.OnClickListener() { Override public void onClick(View v) { if (mediaPlayer ! null !mediaPlayer.isPlaying()) { mediaPlayer.start(); } } }); stopButton.setOnClickListener(new View.OnClickListener() { Override public void onClick(View v) { if (mediaPlayer ! null mediaPlayer.isPlaying()) { mediaPlayer.stop(); // 重新准备MediaPlayer mediaPlayer.prepareAsync(); } } }); } Override protected void onDestroy() { super.onDestroy(); if (mediaPlayer ! null) { mediaPlayer.release(); mediaPlayer null; } } }4 AudioTracker和AudioRecorder我这次项目用的就是这两个其实还是挺简单看个例子就够了。。。#include android/media/AudioTrack.h // 假设audioBuffer是一个已经加载好的音频数据的short数组 short audioBuffer[]; // 音频数据填充到这个数组中 int bufferSize audioTrack-frameCount() * audioTrack-channelCount(); // 计算缓冲区大小 // 创建一个AudioTrack实例 auto audioTrack new android::media::AudioTrack( android::media::AudioTrack::STREAM_MUSIC, // 音频流类型 44100, // 采样率44.1kHz android::media::AudioTrack::CHANNEL_OUT_STEREO, // 立体声输出 android::media::AudioTrack::TRANSFER_MODE_STATIC, // 静态模式 bufferSize, // 缓冲区大小 android::media::AudioTrack::MODE_STATIC // 静态播放模式 ); // 开始播放音频 audioTrack-start(); // 写入数据到AudioTrack缓冲区 audioTrack-write(audioBuffer, bufferSize); // 播放完毕暂停并释放资源 audioTrack-stop(); delete audioTrack;5 HAL这部分位于vendor上面的是位于system所以还是区别很大。如果要在vendor搞事情还是要用这个部分。定义是在这个地方https://android.googlesource.com/platform/hardware/interfaces//refs/heads/master/audio/但是比较疑惑的一点是单位有大神说直接调用Hal会碰坏系统。。。存疑中。。。用的话直接用hardware/audio.h就可以。#include jni.h #include string #include android/log.h #include hardware/hardware.h #include hardware/audio.h #define LOG_TAG NativeAudio #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) extern C JNIEXPORT void JNICALL Java_com_example_audioplayer_MainActivity_nativeInitAudio(JNIEnv *env, jobject thiz) { LOGD(Initializing Audio HAL); hw_module_t *module nullptr; hw_device_t *device nullptr; // Load the audio hardware module if (hw_get_module(AUDIO_HARDWARE_MODULE_ID, (const hw_module_t **)module) 0) { LOGD(Audio module loaded); // Open the audio hardware device if (module-methods-open(module, AUDIO_HARDWARE_INTERFACE, device) 0) { LOGD(Audio device opened); audio_hw_device_t *audioDevice (audio_hw_device_t *)device; if (audioDevice audioDevice-init_check(audioDevice) 0) { LOGD(Audio device initialized); // Set up and start playback using audio_stream_out audio_stream_out_t *streamOut nullptr; audioDevice-open_output_stream(audioDevice, 0, AUDIO_DEVICE_OUT_SPEAKER, AUDIO_OUTPUT_FLAG_NONE, nullptr, streamOut, nullptr); if (streamOut) { LOGD(Audio stream out opened); // Simplified example to play a buffer (should use actual audio data) size_t bufferSize streamOut-common.get_buffer_size(streamOut-common); uint8_t *buffer new uint8_t[bufferSize]; memset(buffer, 0, bufferSize); // Fill buffer with silence or actual audio data streamOut-write(streamOut, buffer, bufferSize); delete[] buffer; audioDevice-close_output_stream(audioDevice, streamOut); } else { LOGD(Failed to open audio stream out); } } else { LOGD(Audio device initialization failed); } device-close(device); } else { LOGD(Failed to open audio device); } } else { LOGD(Failed to load audio module); } }Audio Pipeline:Hardware Interface - ALSA Driver/ASoC - TinyALSA - Audio HAL - Android AudioFlinger.6 ALSATODO这个部分有点略大看看下次写吧。。。还有一个OMX以后有心情再写吧。。。一些调试工具tinymix可以用来调试声卡的驱动。最后回到一开始说的UAC应该是新生成了音频的节点然后可以从这个节点读取音频数据但是最后要将声音从Android的接口放出去所以那么搞。之前调试的时候在UAC的模式下好像也确实是生成了两张声卡。这部分感觉内容也挺多了下次再总结。参考https://source.android.com/docs/core/audio?hlzh-cnAndroid系统Audio框架介绍_android audio-CSDN博客Android系统Audio框架介绍_android audio-CSDN博客
企业数字化 ERP 产品动态
相关推荐
Maven 依赖导入失败 Maven 依赖导入失败
前言:
第一天上班,拉取公司项目,依赖报错… 搞了半天才弄好,恶心呐~看了一些文章,为了方便以后好搞,开始进行记录:
方法一:
简单粗暴:直接 clear清除 compi… · 2026/11/6 3:08:15
Nginx安装方法和反向代理配置 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/7 16:47:14
Windows Mysql 版本更新 Windows Mysql 版本更新
感谢大佬文章,借鉴学习 超详细教你怎么升级Mysql的版本_Mysql_脚本之家 (jb51.net)
前言 软件时代变迁,更新迭代之快,我们每天都需要使用很多的软件… 作为程序员,我们都知道世界上没有完美的软件&#… · 2026/11/7 19:28:44
电工证信息去哪查?真实经历告诉你怎么避免白交培训费 电工证信息去哪查?真实经历告诉你怎么避免白交培训费 怕考不过白交培训费?这事儿我懂,去年我有个徒弟花了几千块报了低压电工证培训,结果考试挂了,钱打水漂,人还特别郁闷。所以今天我掏心窝子给你讲讲【电工证信息去哪查】这个事儿,从考试内容、备考方… · 2026/11/8 11:14:32
公司明知没有电工证如何处理 官方报名入口怎么找 公司明知没有电工证如何处理 官方报名入口怎么找 之前考的证在外省能不能转过来?这个问题其实很多在南阳卧龙区的朋友都问过,特别是那些在培训机构报名、准备考试或者已经拿到证但还在纠结是否要换证的学员。今天就来聊聊,如果公司明知员工没有电工证,该… · 2026/11/8 11:14:32
电工证信息去哪查官方回应最全避坑指南 电工证信息去哪查官方回应最全避坑指南 你是不是也遇到过这种情况?不知道去哪报名怕被中介坑,电工证信息去哪查?官方回应来了,别再被那些“包过”“快速取证”的广告骗了。今天就从你最关心的几个问题出发,手把手教你避开报考陷阱,找到靠谱的报名渠道。… · 2026/11/8 11:14:32
金坛电工证哪里考怎么报名怕考不过白交培训费 金坛电工证哪里考怎么报名怕考不过白交培训费 怕考不过白交培训费?金坛电工证哪里考?别再乱花钱!很多想考电工证的朋友都遇到过这种情况,花了几千块报名,结果考试不过,连个证书都拿不到,培训费打了水漂。今天咱们就来聊聊金坛电工证到底哪里考,怎么报… · 2026/11/8 11:14:32
电工证高级技工证内部消息:平顶山建筑工人避坑全攻略 电工证高级技工证内部消息:平顶山建筑工人避坑全攻略 你是不是也遇到过这种情况?在工地干活几年了,想着考个电工证高级技工证, 不知道去哪报名怕被中介坑 ,结果跑了几家机构,要么要价高得离谱,要么根本不懂考试流程?其实, 内部消息… · 2026/11/8 11:14:32
零陵电工证怎么考官方回应实操考试心里没底怕挂科 零陵电工证怎么考官方回应实操考试心里没底怕挂科 你是不是正为零陵电工证怎么考发愁?尤其是实操考试心里没底,怕挂科?别急,老电工都懂,考试前的焦虑是常态,但真正能改变命运的,是你有没有掌握正确的方法。官方回应,2023年应急管理部对特种作业操… · 2026/11/8 11:13:32
电工证丢失还能补吗?千万别踩坑,丢了证等于失业 电工证丢失还能补吗?千万别踩坑,丢了证等于失业 你正在找工作,但手里的电工证突然丢了,这下怎么办?别急,先别慌, 电工证丢失还能补吗 ?答案是肯定的,但 千万别踩坑 ,补办流程如果不了解,可能会耽误你上岗、甚至影响到你的收入。… · 2026/11/8 0:00:20
电力电缆作业证直播报名入口与办理流程良心建议 电力电缆作业证直播报名入口与办理流程良心建议 你是不是也担心学历不高报不了名?别急,今天就给你讲讲 电力电缆作业证直播 的报名流程和那些你必须知道的干货, 良心建议 在这里,别错过。 电力电缆作业证直播报名需要什么条件?… · 2026/11/8 0:00:20
英德电工证报考费多少钱,怕考不过白交培训费?看完这篇别再踩坑 英德电工证报考费多少钱,怕考不过白交培训费?看完这篇别再踩坑 怕考不过白交培训费?英德电工证报考费多少钱,你真的了解吗?现在市面上培训机构五花八门,价格参差不齐,很多人一不小心就花了冤枉钱,结果还考不过。别急,今天就来给你说清楚英德电工证的… · 2026/11/8 0:00:20
电工证丢失还能补吗?千万别踩坑,丢了证等于失业 电工证丢失还能补吗?千万别踩坑,丢了证等于失业 你正在找工作,但手里的电工证突然丢了,这下怎么办?别急,先别慌, 电工证丢失还能补吗 ?答案是肯定的,但 千万别踩坑 ,补办流程如果不了解,可能会耽误你上岗、甚至影响到你的收入。… · 2026/11/8 0:00:20
电力电缆作业证直播报名入口与办理流程良心建议 电力电缆作业证直播报名入口与办理流程良心建议 你是不是也担心学历不高报不了名?别急,今天就给你讲讲 电力电缆作业证直播 的报名流程和那些你必须知道的干货, 良心建议 在这里,别错过。 电力电缆作业证直播报名需要什么条件?… · 2026/11/8 0:00:20
英德电工证报考费多少钱,怕考不过白交培训费?看完这篇别再踩坑 英德电工证报考费多少钱,怕考不过白交培训费?看完这篇别再踩坑 怕考不过白交培训费?英德电工证报考费多少钱,你真的了解吗?现在市面上培训机构五花八门,价格参差不齐,很多人一不小心就花了冤枉钱,结果还考不过。别急,今天就来给你说清楚英德电工证的… · 2026/11/8 0:00:20
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/7 11:25:08
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/7 12:02:18
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/8 1:18:25