matlab - 阻止从文件流式传输时的音频失真( Octave )

标签 matlab audio file-io octave


我正在设置一个简单的音频 IO 系统,它通过从已存储在内存中的文件一次调用一个 block 来模拟“实时 block 处理”。


此刻,我有一个简单的脚本,它从文件中检索数据,然后进入 while 循环,一次提取一个 block ,并提供 600 Hz 的一阶巴特沃斯低通滤波器(用于测试的框架设置).然后将每个 block 处理并添加到另一个声明在 while 循环范围之外的数组中,以便处理后的数据可以在完成后写入 wave 文件。


为了过滤数据,我使用 Octave signal pkg 生成系数 ( butter ),然后内置 filter应用 IIR 滤波器的函数。

问题是,如果我不应用过滤器影响,即输入 = 输出,音频听起来完全一样。但是,如果我每次调用一个 block 时都应用一个滤波器,则会产生一个振铃,使信号在数字上严重失真。


请参阅以下设置脚本(目前仅处理单声道音频)。

# Reset
close all; clear all;

# Audio file path
fileName = 'test.wav';

# Init routines
[x,fs] = audioread(fileName);
xlen = length(x);
[dim1,dim2] = size(x);
y = zeros(dim1,dim2);
[b,a] = butter(1, (600./(fs*0.5)));    
index = 1;
blockSize = 256;

# Enter process loop
while(index + blockSize < xlen)

  # Extract one block
  audioBlock(:,1) = x(index : index + blockSize - 1, 1);

  # Do process
  outAudioBlock = filter(b,a,audioBlock);

  # Store output block
  y(index : index + blockSize - 1, 1) = outAudioBlock(:);

  # Update index 
  index += blockSize;

endwhile

# Write to outputs
audiowrite('processed.wav', y, fs);
audiowrite('processed1.wav', filter(b,a,y), fs);

第二个 audiowrite 只是一个例子,它确认在一个调用中过滤整个音频数据不会产生失真,而 block 过滤会产生明显的数字失真。


作为旁注:

我还尝试使用不同的滤波技术,包括带窗口的频域乘法,然后 ifft 返回(使用 Octave fftfilt 并仅使用 fft)以及时域卷积并创建重叠相加方法。当应用 FIR 滤波器而不是使用 IIR 系数时,也会出现同样的效果。

我也知道这个例子忽略了最后一个 block 左右的音频,但对于这个用例,我不关心最后一个 block 的零填充。


我不确定我错过了什么;有什么想法吗?

编辑 1:我的想法是尽可能不使用频域处理(只是时域 IIR/FIR 滤波),但我调查了频域乘法以查看是否出现了类似的失真结果(确实如此) ).

最佳答案

这很可能是边缘效应。您将因果 IIR 滤波器应用于 audioBlock .为了计算第一个样本,状态被初始化为全零。如果我没记错的话,这相当于假设第一个样本之前的信号全为零。这可能会产生不连续性,这将影响 block 开头的一定数量的样本。因为您使用 IIR 滤波器,所以这种影响可能会持续很长时间。在这方面使用 FIR 滤波器更安全。

让我们假设 margin sample 受到影响。您可以按如下方式修改代码以将信号扩展该数量并防止失真:

while(index + blockSize < xlen)

  % Extract one block
  if index==1
    audioBlock = x(index : index + blockSize - 1);
  else
    audioBlock = x(index - margin : index + blockSize - 1);
  end

  % Do process
  outAudioBlock = filter(b,a,audioBlock);

  % Store output block
  if index==1
    y(index : index + blockSize - 1) = outAudioBlock;
  else
    y(index : index + blockSize - 1) = outAudioBlock(margin+1:end);
  end

  % Update index 
  index += blockSize;

end

(免责声明:我这里没有安装octave,而且我的MATLAB副本没有信号处理工具箱,所以我无法测试上面的代码。)


不请自来的建议:

  • 你的数据都是一维的,使用一维(线性)索引。它效率更高,输入时间更短。 (见我上面的代码。)

  • 不要做audioBlock(:,1) =当提取一个新的信号位时。只需将结果分配给变量即可。它的速度,并且如果信号大小发生变化并且您忘记重置变量也不会出现问题。

  • 不要以 close all; clear all; 开头.相反,写 function <filename>在脚本的顶部。这会将脚本转换为一个函数,这意味着它有自己的工作区。这是一种更安全的工作方式,因为您不会不小心在脚本中使用现有变量,也不会不小心删除基础工作区中的任何内容。

  • 我使用了 end而不是 endwhile .这是一样的,但也适用于 MATLAB。没有理由不使用最便携的选项。

  • 我使用了 %而不是 # .同样,相同但便携。请注意 SO 语法突出显示如何与 % 一起使用但不是 # ! :)

关于matlab - 阻止从文件流式传输时的音频失真( Octave ),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49275088/

相关文章:

javascript - angular 2 使用具有组件本地成员的 'onended' 音频事件发射器

audio - 机器人如何从 Facebook Messenger (MP4) 接收语音文件并将其转换为 Bing 或 Google 等语音引擎可识别的格式?

C++ - 我使用 fin.ignore() 不正确吗?

c - 如何从文本文件 (C) 中读取特定数据?

matlab - 围绕零值自动构建颜色图

algorithm - 在matlab中使用定点法实现快速优化算法

matlab - SOX 或其他方法来修剪 wav 中的静音而不切入音频

java - 从字符串解析为 DOM 时出现 XML 异常错误

c# - 有没有比这更快的方法来查找目录和所有子目录中的所有文件?

javascript - 控制浏览器声音