mac电脑开发

This commit is contained in:
2026-02-10 14:50:15 +08:00
parent 9119183d21
commit 589fa3e179
2 changed files with 79 additions and 92 deletions
@@ -1,4 +1,4 @@
import { StartAudioRecord, StartAudioRecordOptions } from '../interface.uts'; import { StartAudioRecordOptions } from '../interface.uts';
import { StartAudioRecordFailImpl,AudioErrorCode } from '../unierror.uts'; import { StartAudioRecordFailImpl,AudioErrorCode } from '../unierror.uts';
/** /**
@@ -17,22 +17,11 @@ const isRecording = new AtomicBoolean(false); // 原子布尔值,保证线程
const sampleRate : Int = 16000; // 采样率 const sampleRate : Int = 16000; // 采样率
const channelConfig = AudioFormat.CHANNEL_IN_MONO; // 单声道 const channelConfig = AudioFormat.CHANNEL_IN_MONO; // 单声道
const audioFormat = AudioFormat.ENCODING_PCM_16BIT; // 16位PCM const audioFormat = AudioFormat.ENCODING_PCM_16BIT; // 16位PCM
console.log('channelConfig', channelConfig);
console.log('audioFormat', audioFormat);
const frameSize = 1024; // 对应JS的frameSize:1024
const gain = 1.0; // 对应JS的gain:1.0
const fromSampleRate = 48000; // 设备原始采样率(JS的fromSampleRate:48000
const frameByteSize = frameSize * 2 * 1;
const minBufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat); const minBufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat);
// 最终缓冲区大小:取最小缓冲区和帧字节数的最大值(避免缓冲区过小) // 最终缓冲区大小:取最小缓冲区和帧字节数的最大值(避免缓冲区过小)
const bufferSize = minBufferSize * 2; const bufferSize = minBufferSize * 2;
console.log('bufferSize', bufferSize);
let audioRecord : AudioRecord | null = null; let audioRecord : AudioRecord | null = null;
let recordThread : Thread | null = null; let recordThread : Thread | null = null;
// let isRecording : boolean = false;
// ========== 2. 对外暴露的便捷方法(符合UTS导出规范) ========== // ========== 2. 对外暴露的便捷方法(符合UTS导出规范) ==========
@UTSJS.keepAlive @UTSJS.keepAlive
@@ -7,7 +7,6 @@ import { AudioErrorRes } from "./interface.uts"
*/ */
export const UniErrorSubject = 'ty-recording'; export const UniErrorSubject = 'ty-recording';
/** /**
* 错误信息 * 错误信息
* @UniError * @UniError
@@ -18,114 +17,114 @@ export const UniErrorSubject = 'ty-recording';
* 分段规则:9010001-9010009(权限)、9010010-9010019(初始化)、9010020-9010029(采集)、9010030-9010039(线程)、9010040-9010049(资源)、9010050-9010059(参数)、9010060-9010069(系统/硬件)、9010070+(预留) * 分段规则:9010001-9010009(权限)、9010010-9010019(初始化)、9010020-9010029(采集)、9010030-9010039(线程)、9010040-9010049(资源)、9010050-9010059(参数)、9010060-9010069(系统/硬件)、9010070+(预留)
* @UniError * @UniError
*/ */
export enum AudioErrorCode { export const AudioErrorCode = {
// 权限相关(9010001-9010009 // 权限相关(9010001-9010009
MIC_PERMISSION_NONE = 9010001, // 麦克风权限未授予 MIC_PERMISSION_NONE: 9010001, // 麦克风权限未授予
MIC_PERMISSION_DENIED = 9010002, // 麦克风权限被永久拒绝 MIC_PERMISSION_DENIED: 9010002, // 麦克风权限被永久拒绝
MIC_PERMISSION_GET_FAIL = 9010003,// 获取麦克风权限状态失败 MIC_PERMISSION_GET_FAIL: 9010003,// 获取麦克风权限状态失败
// 初始化相关(9010010-9010019 // 初始化相关(9010010-9010019
AUDIO_RECORD_INIT_FAIL = 9010010, // AudioRecord实例初始化失败 AUDIO_RECORD_INIT_FAIL: 9010010, // AudioRecord实例初始化失败
AUDIO_RECORD_NOT_INIT = 9010011, // AudioRecord未初始化就调用录制/停止 AUDIO_RECORD_NOT_INIT: 9010011, // AudioRecord未初始化就调用录制/停止
AUDIO_RECORD_CREATE_FAIL = 9010012,// AudioRecord实例创建失败(系统资源不足) AUDIO_RECORD_CREATE_FAIL: 9010012,// AudioRecord实例创建失败(系统资源不足)
// 采集过程相关(9010020-9010029 // 采集过程相关(9010020-9010029
RECORD_READ_DATA_FAIL = 9010020, // 音频采集读取数据失败 RECORD_READ_DATA_FAIL: 9010020, // 音频采集读取数据失败
RECORD_INTERRUPTED = 9010021, // 音频采集被中断(如麦克风被抢占) RECORD_INTERRUPTED: 9010021, // 音频采集被中断(如麦克风被抢占)
RECORD_BUFFER_EMPTY = 9010022, // 采集缓冲区无有效数据 RECORD_BUFFER_EMPTY: 9010022, // 采集缓冲区无有效数据
RECORD_START_FAIL = 9010023, // 调用startRecording启动采集失败 RECORD_START_FAIL: 9010023, // 调用startRecording启动采集失败
// 线程相关(9010030-9010039 // 线程相关(9010030-9010039
RECORD_THREAD_CREATE_FAIL = 9010030,// 采集线程创建失败 RECORD_THREAD_CREATE_FAIL: 9010030,// 采集线程创建失败
RECORD_THREAD_START_FAIL = 9010031, // 采集线程启动失败 RECORD_THREAD_START_FAIL: 9010031, // 采集线程启动失败
RECORD_THREAD_INTERRUPT_FAIL = 9010032,// 采集线程中断失败 RECORD_THREAD_INTERRUPT_FAIL: 9010032,// 采集线程中断失败
RECORD_THREAD_CRASH = 9010033, // 采集线程运行崩溃 RECORD_THREAD_CRASH: 9010033, // 采集线程运行崩溃
// 资源释放相关(9010040-9010049 // 资源释放相关(9010040-9010049
RECORD_STOP_FAIL = 9010040, // 调用stop停止采集失败 RECORD_STOP_FAIL: 9010040, // 调用stop停止采集失败
AUDIO_RECORD_RELEASE_FAIL = 9010041,// AudioRecord资源释放失败 AUDIO_RECORD_RELEASE_FAIL: 9010041,// AudioRecord资源释放失败
RECORD_REPEAT_RELEASE = 9010042, // 音频资源重复释放 RECORD_REPEAT_RELEASE: 9010042, // 音频资源重复释放
RECORD_RESOURCE_LEAK = 9010043, // 音频资源泄漏(未正常释放) RECORD_RESOURCE_LEAK: 9010043, // 音频资源泄漏(未正常释放)
// 参数配置相关(9010050-9010059 // 参数配置相关(9010050-9010059
SAMPLE_RATE_NOT_SUPPORT = 9010050, // 采样率不被设备支持 SAMPLE_RATE_NOT_SUPPORT: 9010050, // 采样率不被设备支持
CHANNEL_CONFIG_ILLEGAL = 9010051, // 声道配置非法/不支持 CHANNEL_CONFIG_ILLEGAL: 9010051, // 声道配置非法/不支持
AUDIO_FORMAT_ILLEGAL = 9010052, // 音频格式非法/不支持 AUDIO_FORMAT_ILLEGAL: 9010052, // 音频格式非法/不支持
BUFFER_SIZE_TOO_SMALL = 9010053, // 采集缓冲区大小过小(低于系统最小值) BUFFER_SIZE_TOO_SMALL: 9010053, // 采集缓冲区大小过小(低于系统最小值)
BUFFER_SIZE_ILLEGAL = 9010054, // 采集缓冲区大小配置非法 BUFFER_SIZE_ILLEGAL: 9010054, // 采集缓冲区大小配置非法
// 系统/硬件/外部冲突(9010060-9010069 // 系统/硬件/外部冲突(9010060-9010069
MIC_OCCUPIED = 9010060, // 麦克风被其他应用占用 MIC_OCCUPIED: 9010060, // 麦克风被其他应用占用
AUDIO_HARDWARE_ERROR = 9010061, // 音频硬件故障 AUDIO_HARDWARE_ERROR: 9010061, // 音频硬件故障
SYSTEM_RESOURCE_INSUFFICIENT = 9010062,// 系统资源不足(无法创建音频实例) SYSTEM_RESOURCE_INSUFFICIENT: 9010062,// 系统资源不足(无法创建音频实例)
AUDIO_SERVICE_EXCEPTION = 9010063,// 系统音频服务异常/未启动 AUDIO_SERVICE_EXCEPTION: 9010063,// 系统音频服务异常/未启动
// 通用业务异常(9010070-9010079 // 通用业务异常(9010070-9010079
RECORD_REPEAT_START = 9010070, // 重复启动音频录制 RECORD_REPEAT_START: 9010070, // 重复启动音频录制
RECORD_NOT_RUNNING = 9010071, // 未在录制状态却调用停止/暂停 RECORD_NOT_RUNNING: 9010071, // 未在录制状态却调用停止/暂停
BYTE_ARRAY_COPY_FAIL = 9010072, // 音频数据缓冲区拷贝失败 BYTE_ARRAY_COPY_FAIL: 9010072, // 音频数据缓冲区拷贝失败
// 预留扩展(9010080+ // 预留扩展(9010080+
RESERVED_01 = 9010080 RESERVED_01: 9010080
} }
/** /**
* 音频录制错误码-错误信息映射表 * 音频录制错误码-错误信息映射表
* AudioErrorCode枚举一一对应,提供友好的用户/开发提示 * 使用AudioErrorCode常量作为键,避免硬编码数字,提升可维护性
* @UniError * @UniError
*/ */
export const AudioErrors : Map<AudioErrorCode, string> = new Map([ export const AudioErrors = new Map<number, string>([
// 权限相关 // 权限相关
[AudioErrorCode.MIC_PERMISSION_NONE, '麦克风权限未授予,请先在设置开启'], [AudioErrorCode.MIC_PERMISSION_NONE, '麦克风权限未授予,请前往设置开启'],
[AudioErrorCode.MIC_PERMISSION_DENIED, '麦克风权限被永久拒绝,请前往应用设置手动开启'], [AudioErrorCode.MIC_PERMISSION_DENIED, '麦克风权限被永久拒绝,请前往设置开启'],
[AudioErrorCode.MIC_PERMISSION_GET_FAIL, '获取麦克风权限状态失败,请检查应用权限配置'], [AudioErrorCode.MIC_PERMISSION_GET_FAIL, '获取麦克风权限状态失败'],
// 初始化相关 // 初始化相关
[AudioErrorCode.AUDIO_RECORD_INIT_FAIL, '音频录制实例初始化失败,可能是参数不支持或系统异常'], [AudioErrorCode.AUDIO_RECORD_INIT_FAIL, '音频录制实例初始化失败'],
[AudioErrorCode.AUDIO_RECORD_NOT_INIT, '音频录制实例未初始化,无法执行操作'], [AudioErrorCode.AUDIO_RECORD_NOT_INIT, '音频录制实例未初始化,无法执行操作'],
[AudioErrorCode.AUDIO_RECORD_CREATE_FAIL, '创建音频录制实例失败,系统音频资源不足'], [AudioErrorCode.AUDIO_RECORD_CREATE_FAIL, '系统资源不足,无法创建音频录制实例'],
// 采集过程相关 // 采集过程相关
[AudioErrorCode.RECORD_READ_DATA_FAIL, '音频采集读取数据失败,建议停止后重新启动'], [AudioErrorCode.RECORD_READ_DATA_FAIL, '音频采集读取数据失败'],
[AudioErrorCode.RECORD_INTERRUPTED, '音频采集被中断麦克风可能被其他应用抢占'], [AudioErrorCode.RECORD_INTERRUPTED, '音频采集被中断麦克风被其他应用抢占'],
[AudioErrorCode.RECORD_BUFFER_EMPTY, '音频采集缓冲区无有效数据,采集异常'], [AudioErrorCode.RECORD_BUFFER_EMPTY, '音频采集缓冲区无有效数据'],
[AudioErrorCode.RECORD_START_FAIL, '启动音频采集失败,实例状态异常'], [AudioErrorCode.RECORD_START_FAIL, '启动音频采集失败'],
// 线程相关 // 线程相关
[AudioErrorCode.RECORD_THREAD_CREATE_FAIL, '创建音频采集线程失败,系统资源不足'], [AudioErrorCode.RECORD_THREAD_CREATE_FAIL, '采集线程创建失败'],
[AudioErrorCode.RECORD_THREAD_START_FAIL, '启动音频采集线程失败,线程状态异常'], [AudioErrorCode.RECORD_THREAD_START_FAIL, '采集线程启动失败'],
[AudioErrorCode.RECORD_THREAD_INTERRUPT_FAIL, '中断音频采集线程失败,线程已异常'], [AudioErrorCode.RECORD_THREAD_INTERRUPT_FAIL, '采集线程中断失败'],
[AudioErrorCode.RECORD_THREAD_CRASH, '音频采集线程运行崩溃,具体原因请查看日志'], [AudioErrorCode.RECORD_THREAD_CRASH, '采集线程运行崩溃'],
// 资源释放相关 // 资源释放相关
[AudioErrorCode.RECORD_STOP_FAIL, '停止音频采集失败,录制实例状态异常'], [AudioErrorCode.RECORD_STOP_FAIL, '停止音频采集失败'],
[AudioErrorCode.AUDIO_RECORD_RELEASE_FAIL, '释放音频录制资源失败,可能存在资源泄漏'], [AudioErrorCode.AUDIO_RECORD_RELEASE_FAIL, '音频录制资源释放失败'],
[AudioErrorCode.RECORD_REPEAT_RELEASE, '音频录制资源已释放,请勿重复执行释放操作'], [AudioErrorCode.RECORD_REPEAT_RELEASE, '音频资源重复释放'],
[AudioErrorCode.RECORD_RESOURCE_LEAK, '音频录制资源未正常释放,建议检查停止逻辑'], [AudioErrorCode.RECORD_RESOURCE_LEAK, '音频资源泄漏(未正常释放)'],
// 参数配置相关 // 参数配置相关
[AudioErrorCode.SAMPLE_RATE_NOT_SUPPORT, '当前设备不支持该采样率,建议切换为16000/44100Hz'], [AudioErrorCode.SAMPLE_RATE_NOT_SUPPORT, '当前设备不支持该采样率'],
[AudioErrorCode.CHANNEL_CONFIG_ILLEGAL, '声道配置非法或当前设备不支持,建议使用单声道'], [AudioErrorCode.CHANNEL_CONFIG_ILLEGAL, '声道配置非法或不被支持'],
[AudioErrorCode.AUDIO_FORMAT_ILLEGAL, '音频格式非法或当前设备不支持,建议使用PCM_16BIT'], [AudioErrorCode.AUDIO_FORMAT_ILLEGAL, '音频格式非法或不被支持'],
[AudioErrorCode.BUFFER_SIZE_TOO_SMALL, '采集缓冲区过小,已自动调整为系统最小缓冲区'], [AudioErrorCode.BUFFER_SIZE_TOO_SMALL, '采集缓冲区大小低于系统最小'],
[AudioErrorCode.BUFFER_SIZE_ILLEGAL, '采集缓冲区大小配置非法,已使用系统默认值'], [AudioErrorCode.BUFFER_SIZE_ILLEGAL, '采集缓冲区大小配置非法'],
// 系统/硬件/外部冲突 // 系统/硬件/外部冲突
[AudioErrorCode.MIC_OCCUPIED, '麦克风被其他应用占用,请关闭后重新尝试'], [AudioErrorCode.MIC_OCCUPIED, '麦克风被其他应用占用'],
[AudioErrorCode.AUDIO_HARDWARE_ERROR, '音频硬件故障,请检查设备麦克风是否正常'], [AudioErrorCode.AUDIO_HARDWARE_ERROR, '音频硬件故障'],
[AudioErrorCode.SYSTEM_RESOURCE_INSUFFICIENT, '系统资源不足,无法创建音频录制实例'], [AudioErrorCode.SYSTEM_RESOURCE_INSUFFICIENT, '系统资源不足,无法创建音频实例'],
[AudioErrorCode.AUDIO_SERVICE_EXCEPTION, '系统音频服务异常,请重启设备后重新尝试'], [AudioErrorCode.AUDIO_SERVICE_EXCEPTION, '系统音频服务异常或未启动'],
// 通用业务异常 // 通用业务异常
[AudioErrorCode.RECORD_REPEAT_START, '当前正在录制中,请勿重复启动音频录制'], [AudioErrorCode.RECORD_REPEAT_START, '重复启动音频录制'],
[AudioErrorCode.RECORD_NOT_RUNNING, '未在音频录制状态,无执行停止操作'], [AudioErrorCode.RECORD_NOT_RUNNING, '未在录制状态,无执行停止/暂停操作'],
[AudioErrorCode.BYTE_ARRAY_COPY_FAIL, '音频数据缓冲区拷贝失败,采集数据可能损坏'], [AudioErrorCode.BYTE_ARRAY_COPY_FAIL, '音频数据缓冲区拷贝失败'],
// 预留扩展 // 预留扩展
[AudioErrorCode.RESERVED_01, '预留错误码,暂未定义'] [AudioErrorCode.RESERVED_01, '预留错误码']
]); ]);
/** /**
* 错误对象实现 * 错误对象实现
*/ */
@@ -134,13 +133,12 @@ export class StartAudioRecordFailImpl extends UniError implements AudioErrorRes
/** /**
* 错误对象构造函数 * 错误对象构造函数
*/ */
constructor(errCode : AudioErrorCode) { constructor(errCode : any) {
super(); super();
this.errSubject = UniErrorSubject; this.errSubject = UniErrorSubject;
const _errCode = errCode as number
// @ts-ignore 忽略"value属性不存在"的假报错(运行时存在) this.errCode = _errCode;
this.errCode = errCode.value as number; this.errMsg = AudioErrors.get(_errCode) as string;
this.errMsg = AudioErrors.get(errCode) ?? "";
} }
} }