matlabaudiofile-iooctave# Audio distortion when block streaming from a file (Octave)

I am setting up a simple audio IO system which simulates 'real-time block processing' by calling a block at a time from a file that is already stored in memory.

At the minute, I have a simple script which retreives the data from a file, and then enters a while loop which extracts one block at a time and provides a first order butterworth lowpass filter at 600 Hz (a skeleton setup to test). Each block is then processed and added onto another array which is declared outside the scope of the while loop, so that the processed data can be written to a wave file after completion.

To filter the data I am using the Octave *signal* pkg to generate the coefficients (butter), and then the built in filter function to apply the IIR filter.

**The problem is that if I apply no filter affect i.e. input = output the audio sounds the exact same. However, if I apply a filter every time a block is called, a ringing is created that digitally distorts the signal quite heavily.**

Please see the following script for the setup (it is only handling mono audio for the minute).

```
# 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);
```

The second audiowrite is just an example which confirms filtering the whole audio data in one call creates no distortion, wheareas the block filtering creates noticeable digital distortion.

As a side note :

I have also attempted using different filtering techniques with frequency domain multiplication with windowing and then ifft back (with octaves fftfilt & using just the fft) as well as time domain convolution and creating an overlap add method. The same effect also occurs when applying an FIR filter rather than using IIR coefficients.

I am also aware that this example disregards the last block or so of audio but for this use case I am not bothered with the last block's zero padding.

I am not sure what I am missing; any ideas?

**EDIT 1: The idea was not to use frequency domain processing if possible (just the time domain IIR/FIR filtering), but I investigated the frequency domain multiplications to see if a similar distortion result occured (which it did).**

Solution

This is most likely an edge effect thing. You apply a causal IIR filter to `audioBlock`

. To compute the first sample, the state is initialized to all zeros. If I remember correctly, this is equivalent to assuming that the signal before the first sample is all zeros. This likely creates a discontinuity, which will affect a certain number of samples at the beginning of the block. Because you use an IIR filter, this effect could potentially carry on for a long time. Using a FIR filter is safer in that respect.

Let's assume `margin`

samples are affected. You could amend your code as follows to extend your signal by that amount and prevent the distortion:

```
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
```

(Disclaimer: I don't have octave installed here, and my copy of MATLAB doesn't have the signal processing toolbox, so I cannot test the above code.)

**Unsolicited advice:**

Your data is all 1D, use 1D (linear) indexing. It's more efficient, and shorter to type. (See my code above.)

Don't do

`audioBlock(:,1) =`

when extracting a new bit of signal. Simply assign the result to the variable. It's*much*faster, and won't give problems if the signal size changes and you forget to reset the variable.Don't start with

`close all; clear all;`

. Instead, write`function <filename>`

at the top of the script. This converts the script into a function, meaning it gets its own workspace. This is a much safer way of working, as you don't accidentally use existing variables in your script, and you don't accidentally erase anything in your base workspace.I used

`end`

instead of`endwhile`

. This is the same, but also works on MATLAB. There is no reason not to use the most portable option.I used

`%`

instead of`#`

. Again, the same but portable. Note how the SO syntax highlighting works with`%`

but not`#`

! :)

- Implementing a Harris corner detector
- Import a custom validation function for use in the arguments block
- Is it possible to enforce input argument data types in MATLAB?
- Programmatically Labeling a Signal in Simulink
- How to convolve a function with delta function in Matlab?
- Converting a 3D array to a 2D array in Matlab
- MATLAB encountered an internal error and needs to close
- Matlab - putting a square hole in a square plane
- Strange behavior of `copyfile` regarding symlinks on Linux and macOS
- How can I get around this error using deval with dde23 in MATLAB?
- How can I read value from a json file and use it in the MATLAB plot function?
- Sort JSON by values in MATLAB
- Plot control at one figure and two subplots using built-in matlab functions
- Other ways to efficiently search within an array
- Hash tables in MATLAB
- How to use Hash Tables (dictionaries) in MATLAB?
- How to zoom in/out in Matlab editor?
- MATLAB: Why does my Kalman filter not work for non-zero input?
- How to use subsystem output as its input in the next iteration in simulink
- How can I generate 3-d random points with minimum distance between each of them?
- Setting a Specific Formula for PID Controller in Simulink (Matlab)
- InputParser vs exist(...,'var') vs nargin performance
- 'cdfread' not reading .cdf file Matlab
- create the complete symmetric matrix by copying the lower triangular of a sparse matrix in triplet format
- How to optimize the running speed of nested loops in matlab
- How to calculate the area of each grid cell?
- `annotation` outside permitted figure bounds
- Get symbolic expression from residue result
- MATLAB volume plots via transparent isosurfaces, like in Plotly
- How to Implement Box Function in better way in Matlab?