You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Delphi 11 FMX的Android应用中禁用录制音频效果

Delphi 11 FMX Android 音频录制:禁用系统音频效果解决电平异常问题

核心问题分析

系统默认的自动增益(AGC)、降噪(NS)等音频效果会在部分设备上干扰录制电平,导致音量异常、低频衰减等问题。需针对当前AudioRecord实例的音频会话,绑定并禁用这些系统级效果。

分步解决方案

1. 正确获取AudioRecord的会话ID(Session ID)

所有音频效果必须绑定到当前AudioRecord实例的会话ID,不能使用AUDIO_SESSION_ID_GENERATE。初始化FAudioRecord后立即获取:

var
  LSessionID: Integer;
begin
  // 初始化FAudioRecord后获取会话ID
  LSessionID := (FAudioRecord as JAudioRecord).getAudioSessionId;
end;

2. 禁用自动增益控制(AGC)

使用TJAutomaticGainControl类,先检查设备兼容性,再绑定会话并禁用:

var
  LAGC: JAutomaticGainControl;
begin
  // API 16及以上支持AGC
  if TJBuild_VERSION.JavaClass.SDK_INT >= 16 then
  begin
    if TJAutomaticGainControl.JavaClass.isAvailable then
    begin
      LAGC := TJAutomaticGainControl.JavaClass.create(LSessionID);
      if Assigned(LAGC) then
        LAGC.setEnabled(False); // 禁用自动增益
    end;
  end;
end;

3. 禁用降噪(Noise Suppression)

类似AGC,使用TJNoiseSuppressor类处理降噪效果:

var
  LNS: JNoiseSuppressor;
begin
  // API 17及以上支持降噪
  if TJBuild_VERSION.JavaClass.SDK_INT >= 17 then
  begin
    if TJNoiseSuppressor.JavaClass.isAvailable then
    begin
      LNS := TJNoiseSuppressor.JavaClass.create(LSessionID);
      if Assigned(LNS) then
        LNS.setEnabled(False); // 禁用降噪
    end;
  end;
end;

4. 处理均衡器初始化异常

TJEqualizer多针对播放场景,录制端很多设备不支持。若必须使用,需做兼容性检查和异常捕获:

var
  LEQ: JEqualizer;
begin
  try
    if TJEqualizer.JavaClass.isAvailable then
    begin
      LEQ := TJEqualizer.JavaClass.create(0, LSessionID); // 0为优先级参数
      if Assigned(LEQ) then
        LEQ.setEnabled(False); // 禁用均衡器效果
    end;
  except
    // 捕获初始化异常,跳过均衡器处理
  end;
end;

5. 权限确认与动态申请

确保AndroidManifest.xml中添加必要权限:

<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />

注意:RECORD_AUDIO需要动态申请,启动录制前需执行权限检查:

uses
  Androidapi.Helpers, Androidapi.JNI.Os;

function CheckRecordPermission: Boolean;
var
  LPermission: JString;
begin
  LPermission := StringToJString('android.permission.RECORD_AUDIO');
  Result := TAndroidHelper.Activity.checkSelfPermission(LPermission) = TJPackageManager.JavaClass.PERMISSION_GRANTED;
  if not Result then
    TAndroidHelper.Activity.requestPermissions(TJavaObjectArray<JString>.Create(1, LPermission), 100);
end;

完整修正后的录制初始化代码

var
  FChannelConfig: Integer;
  FAudioFormat: Integer;
  FTailleBufferBytes: Integer;
  AUDIO_SOURCE: Integer;
  FAudioManager: JAudioManager;
  AudioMngrProp: JString;
  FAudioRecord: JAudioRecord;
  LSessionID: Integer;
  LAGC: JAutomaticGainControl;
  LNS: JNoiseSuppressor;
begin
  FChannelConfig := TJAudioFormat.JavaClass.CHANNEL_IN_STEREO;
  FAudioFormat := TJAudioFormat.JavaClass.ENCODING_PCM_16BIT;
  FTailleBufferBytes := TJAudioRecord.JavaClass.getMinBufferSize(FSampleRate, FChannelConfig, FAudioFormat);

  // VOICE_RECOGNITION
  AUDIO_SOURCE := TJMediaRecorder_AudioSource.JavaClass.VOICE_RECOGNITION;

  // UNPROCESSED 音频源(API 24+),优先使用可绕过部分系统处理
  if (TJBuild_VERSION.JavaClass.SDK_INT >= 24) then
  begin
    FAudioManager := TJAudioManager.Wrap((TAndroidHelper.Activity.getSystemService(TJContext.JavaClass.AUDIO_SERVICE) as ILocalObject).GetObjectID);
    AudioMngrProp := FAudioManager.getProperty(TJAudioManager.JavaClass.PROPERTY_SUPPORT_AUDIO_SOURCE_UNPROCESSED);
    if (Boolean.Parse(JStringToString(AudioMngrProp))) then
      AUDIO_SOURCE := TJMediaRecorder_AudioSource.JavaClass.UNPROCESSED;
  end;

  // 检查录音权限
  if not CheckRecordPermission then
  begin
    // 权限未授予,执行提示或退出逻辑
    Exit;
  end;

  // 初始化AudioRecord
  FAudioRecord := TJAudioRecord.JavaClass.init(AUDIO_SOURCE, FSampleRate, FChannelConfig, FAudioFormat, FTailleBufferBytes);

  // 获取会话ID
  LSessionID := (FAudioRecord as JAudioRecord).getAudioSessionId;

  // 禁用自动增益
  if TJBuild_VERSION.JavaClass.SDK_INT >= 16 then
  begin
    if TJAutomaticGainControl.JavaClass.isAvailable then
    begin
      LAGC := TJAutomaticGainControl.JavaClass.create(LSessionID);
      if Assigned(LAGC) then
        LAGC.setEnabled(False);
    end;
  end;

  // 禁用降噪
  if TJBuild_VERSION.JavaClass.SDK_INT >= 17 then
  begin
    if TJNoiseSuppressor.JavaClass.isAvailable then
    begin
      LNS := TJNoiseSuppressor.JavaClass.create(LSessionID);
      if Assigned(LNS) then
        LNS.setEnabled(False);
    end;
  end;

  // 可选:禁用均衡器(按需启用)
  // try
  //   if TJEqualizer.JavaClass.isAvailable then
  //   begin
  //     LEQ := TJEqualizer.JavaClass.create(0, LSessionID);
  //     if Assigned(LEQ) then
  //       LEQ.setEnabled(False);
  //   end;
  // except
  // end;

  // 开始录制
  (FAudioRecord As JAudioRecord).StartRecording;
end;

关键注意事项

  • 所有音频效果配置必须在FAudioRecord初始化后、StartRecording前完成,确保效果绑定到正确会话。
  • 部分设备可能不支持特定效果,必须做可用性检查和异常捕获,避免崩溃。
  • 优先使用UNPROCESSED音频源(API 24+),可直接绕过大部分系统音频处理,是解决电平异常的最优方案。

内容的提问来源于stack exchange,提问作者lefjucabro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 20:13:19