Last Details
Last updated
Last updated
In the previous section we implemented a basic granular synthesis voice transformer that lowers the pitch of the input voice. In this section we will address some remaining issues, namely:
implement an effect that raises the pitch of the voice (aka the "Chipmunks" effect)
properly initialize the buffer as a function of the pitch change
optimize the code a little more
To raise the pitch of the voice we need to set to values larger than one. As we have seen, this makes the effect noncausal, which we need to address by introducing some processing delay.
The way to achieve this is to place the audio buffer's input index forward with respect to the output index; let's do this properly by creating an initialization function for the buffer that takes the resampling factor as the input.
TASK 1: Determine the proper initial value for buf_ix
when in the function below.
By now you know where to place this code but don't forget to
add the following line to the file main.h
between the /* USER CODE BEGIN Includes */
tags.
declare the function prototype in the USER CODE BEGIN PFP
block
call the function before launching the DMA transfers:
We can use the blue button on the Nucleo board to switch between Darth Vader and the Chipmunks; to do so, define the following constants at the beginning of the code
and modify the user button callback like so:
In the main processing loop, we are performing two checks on the value of grain_m
per output sample. However, in the current implementation, both the stride and the taper lengths are multiples of the size of the DMA half-buffer. This allows us to move these checks outside of the processing loop and perform them once per call rather than once per sample
TASK 2: Modify the VoiceEffect()
function to reduce the number of if
statements per call. Benchmark the result and observe the change in performance.
Are you ready to see the answers ? :)
We have seen in the previous section that the maximum displacement between current output index and needed input index is . Since this value can be non-integer, we round it up to the nearest integer value:
With this implementation, the computational cost per sample oscillates between and per sample, which represents a saving of almost one microsecond per sample or, equivalently, a performance increase of at least 9%.